Skip to content

Commit 5af0cb7

Browse files
christophstroblmp911de
authored andcommitted
Add native jpa sample.
See #654
1 parent d172c56 commit 5af0cb7

File tree

11 files changed

+463
-0
lines changed

11 files changed

+463
-0
lines changed

jpa/graalvm-native/README.adoc

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
== Spring Data Jpa - GraalVM native image
2+
3+
This example compiles a basic Spring Data Jpa application into a GraalVM native image.
4+
5+
=== Install GraalVM & native image tooling
6+
7+
Download and install GraalVM using https://sdkman.io/[SDKMAN!].
8+
9+
```
10+
$> sdk install java <recent version>.r17-grl
11+
$> gu install native-image
12+
```
13+
14+
=== Compile to native image
15+
16+
The maven build uses a dedicated profile `native` to trigger the native image creation.
17+
18+
```
19+
$> maven clean package -P native
20+
```
21+
22+
This will create the native executable in the target folder.
23+
24+
=== Run the image
25+
26+
Run the image directly from your console as shown below.
27+
This will print results of crud functions invoked via a `CommandLineRunner`.
28+
29+
```
30+
$> ./target/spring-data-jpa-graalvm-native
31+
32+
. ____ _ __ _ _
33+
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
34+
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
35+
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
36+
' |____| .__|_| |_|_| |_\__, | / / / /
37+
=========|_|==============|___/=/_/_/_/
38+
:: Spring Boot :: (v3.0.0-SNAPSHOT)
39+
40+
INFO 82562 --- [ main] e.s.j.g.GraalvmNativeApplication : Starting GraalvmNativeApplication using Java 17.0.4 with PID 51404
41+
INFO 51404 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
42+
INFO 51404 --- [ main] c.example.data.jpa.DataJpaApplication : Started DataJpaApplication in 0.079 seconds (process running for 0.097)
43+
insertAuthors(): author1 = Author{name='Josh Long'}
44+
insertAuthors(): author2 = Author{name='Martin Kleppmann'}
45+
listAllAuthors(): author = Author{name='Josh Long'}
46+
Book{title='Reactive Spring'}
47+
...
48+
```

jpa/graalvm-native/pom.xml

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0"
2+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<artifactId>spring-data-jpa-graalvm-native</artifactId>
7+
8+
<parent>
9+
<groupId>org.springframework.data.examples</groupId>
10+
<artifactId>spring-data-examples</artifactId>
11+
<version>2.0.0.BUILD-SNAPSHOT</version>
12+
</parent>
13+
14+
<name>Spring Data JPA - GraalVM Native Image</name>
15+
16+
<dependencies>
17+
<dependency>
18+
<groupId>org.springframework.boot</groupId>
19+
<artifactId>spring-boot-starter-data-jpa</artifactId>
20+
</dependency>
21+
22+
<dependency>
23+
<groupId>com.h2database</groupId>
24+
<artifactId>h2</artifactId>
25+
<scope>runtime</scope>
26+
</dependency>
27+
<dependency>
28+
<groupId>org.springframework.boot</groupId>
29+
<artifactId>spring-boot-starter-test</artifactId>
30+
<scope>test</scope>
31+
</dependency>
32+
<dependency>
33+
<groupId>jakarta.persistence</groupId>
34+
<artifactId>jakarta.persistence-api</artifactId>
35+
<version>3.0.0</version>
36+
</dependency>
37+
</dependencies>
38+
39+
<build>
40+
<plugins>
41+
<plugin>
42+
<groupId>org.springframework.boot</groupId>
43+
<artifactId>spring-boot-maven-plugin</artifactId>
44+
</plugin>
45+
<plugin>
46+
<groupId>org.hibernate.orm.tooling</groupId>
47+
<artifactId>hibernate-enhance-maven-plugin</artifactId>
48+
<version>6.1.4.Final</version>
49+
<executions>
50+
<execution>
51+
<configuration>
52+
<enableLazyInitialization>true</enableLazyInitialization>
53+
<enableDirtyTracking>true</enableDirtyTracking>
54+
<enableAssociationManagement>true</enableAssociationManagement>
55+
</configuration>
56+
<goals>
57+
<goal>enhance</goal>
58+
</goals>
59+
</execution>
60+
</executions>
61+
</plugin>
62+
</plugins>
63+
</build>
64+
65+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.example.data.jpa;
17+
18+
import java.util.Optional;
19+
20+
import com.example.data.jpa.model.Author;
21+
22+
import org.springframework.data.jpa.repository.Query;
23+
import org.springframework.data.repository.ListCrudRepository;
24+
25+
public interface AuthorRepository extends ListCrudRepository<Author, Long> {
26+
27+
Optional<Author> findByNameContainingIgnoreCase(String partialName);
28+
29+
@Query("SELECT a FROM Author a WHERE a.name = :name")
30+
Optional<Author> queryFindByName(String name);
31+
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.example.data.jpa;
17+
18+
import java.util.Arrays;
19+
import java.util.List;
20+
import java.util.Set;
21+
22+
import com.example.data.jpa.model.Author;
23+
import com.example.data.jpa.model.Book;
24+
25+
import org.springframework.boot.CommandLineRunner;
26+
import org.springframework.stereotype.Component;
27+
import org.springframework.transaction.annotation.Transactional;
28+
29+
@Component
30+
class CLR implements CommandLineRunner {
31+
32+
private final AuthorRepository authorRepository;
33+
34+
CLR(AuthorRepository authorRepository) {
35+
this.authorRepository = authorRepository;
36+
}
37+
38+
@Override
39+
@Transactional
40+
public void run(String... args) {
41+
var authors = insertAuthors();
42+
listAllAuthors();
43+
findById(authors);
44+
findByPartialName();
45+
queryFindByName();
46+
deleteAll();
47+
}
48+
49+
private void deleteAll() {
50+
this.authorRepository.deleteAll();
51+
long count = this.authorRepository.count();
52+
System.out.printf("deleteAll(): count = %d%n", count);
53+
}
54+
55+
private void queryFindByName() {
56+
Author author1 = this.authorRepository.queryFindByName("Josh Long").orElse(null);
57+
Author author2 = this.authorRepository.queryFindByName("Martin Kleppmann").orElse(null);
58+
59+
System.out.printf("queryFindByName(): author1 = %s%n", author1);
60+
System.out.printf("queryFindByName(): author2 = %s%n", author2);
61+
}
62+
63+
private void findByPartialName() {
64+
Author author1 = this.authorRepository.findByNameContainingIgnoreCase("sh lo").orElse(null);
65+
Author author2 = this.authorRepository.findByNameContainingIgnoreCase("in kl").orElse(null);
66+
67+
System.out.printf("findByPartialName(): author1 = %s%n", author1);
68+
System.out.printf("findByPartialName(): author2 = %s%n", author2);
69+
}
70+
71+
private void findById(List<Author> authors) {
72+
Author author1 = this.authorRepository.findById(authors.get(0).getId()).orElse(null);
73+
Author author2 = this.authorRepository.findById(authors.get(1).getId()).orElse(null);
74+
75+
System.out.printf("findById(): author1 = %s%n", author1);
76+
System.out.printf("findById(): author2 = %s%n", author2);
77+
}
78+
79+
private void listAllAuthors() {
80+
List<Author> authors = this.authorRepository.findAll();
81+
for (Author author : authors) {
82+
System.out.printf("listAllAuthors(): author = %s%n", author);
83+
for (Book book : author.getBooks()) {
84+
System.out.printf("\t%s%n", book);
85+
}
86+
}
87+
}
88+
89+
private List<Author> insertAuthors() {
90+
Author author1 = this.authorRepository.save(new Author(null, "Josh Long",
91+
Set.of(new Book(null, "Reactive Spring"), new Book(null, "Cloud Native Java"))));
92+
Author author2 = this.authorRepository.save(
93+
new Author(null, "Martin Kleppmann", Set.of(new Book(null, "Designing Data Intensive Applications"))));
94+
95+
System.out.printf("insertAuthors(): author1 = %s%n", author1);
96+
System.out.printf("insertAuthors(): author2 = %s%n", author2);
97+
98+
return Arrays.asList(author1, author2);
99+
}
100+
101+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.example.data.jpa;
17+
18+
import org.springframework.boot.SpringApplication;
19+
import org.springframework.boot.autoconfigure.SpringBootApplication;
20+
21+
@SpringBootApplication
22+
public class DataJpaApplication {
23+
24+
public static void main(String[] args) throws InterruptedException {
25+
SpringApplication.run(DataJpaApplication.class, args);
26+
}
27+
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.example.data.jpa.model;
17+
18+
import java.util.Objects;
19+
import java.util.Set;
20+
21+
import jakarta.persistence.CascadeType;
22+
import jakarta.persistence.Entity;
23+
import jakarta.persistence.GeneratedValue;
24+
import jakarta.persistence.Id;
25+
import jakarta.persistence.OneToMany;
26+
27+
@Entity
28+
public class Author {
29+
30+
@Id
31+
@GeneratedValue
32+
private Long id;
33+
34+
private String name;
35+
36+
@OneToMany(cascade = CascadeType.ALL)
37+
private Set<Book> books;
38+
39+
protected Author() {
40+
}
41+
42+
public Author(Long id, String name, Set<Book> books) {
43+
this.id = id;
44+
this.name = name;
45+
this.books = books;
46+
}
47+
48+
public Long getId() {
49+
return id;
50+
}
51+
52+
public String getName() {
53+
return name;
54+
}
55+
56+
public void setName(String name) {
57+
this.name = name;
58+
}
59+
60+
public Set<Book> getBooks() {
61+
return books;
62+
}
63+
64+
@Override
65+
public boolean equals(Object o) {
66+
if (this == o) {
67+
return true;
68+
}
69+
if (o == null || getClass() != o.getClass()) {
70+
return false;
71+
}
72+
Author author = (Author) o;
73+
return Objects.equals(id, author.id) && Objects.equals(name, author.name)
74+
&& Objects.equals(books, author.books);
75+
}
76+
77+
@Override
78+
public int hashCode() {
79+
return Objects.hash(id, name, books);
80+
}
81+
82+
@Override
83+
public String toString() {
84+
return "Author{" + "name='" + name + '\'' + '}';
85+
}
86+
87+
}

0 commit comments

Comments
 (0)