Skip to content

Commit 649969a

Browse files
committed
Refine AOT example documentation.
1 parent 9725374 commit 649969a

File tree

9 files changed

+375
-19
lines changed

9 files changed

+375
-19
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
= Spring Data Cassandra - Ahead of Time Repository Optimization Example
2+
3+
The project shows the usage of AOT Repositories.
4+
Ahead of Time Repositories implement query methods through code contribution and allow for debugging queries during runtime.
5+
Additionally, AOT repositories improve startup time and reduce memory consumption because AOT optimized query methods do not require reflective introspection.
6+
Each AOT repository is documented with a JSON file that describes the queries implemented by the repository.
7+
8+
== Using AOT Repositories
9+
10+
Repository AOT processing is enabled by default when using Spring Boot's AOT processing (see `pom.xml` for `spring-boot-maven-plugin` usage).
11+
AOT processing generates AOT artifacts to `target/spring-aot` and through the regular build.
12+
When using the JVM mode (not Graal Native Images), then you need to enable AOT mode on the JVM when running your application through `-Dspring.aot.enabled=true`.
13+
14+
[source,bash]
15+
----
16+
$ mvn clean package
17+
$ java -Dspring.aot.enabled=true -jar target/spring-data-cassandra-aot-optimization-4.0.0-SNAPSHOT.jar
18+
----
19+
20+
You can find more details about AOT processing in the https://docs.spring.io/spring-data/cassandra/reference/5.0/cassandra/repositories/aot.html#aot.repositories[Spring Data Cassandra Reference Documentation].
21+
22+
== AOT Repository
23+
24+
**`UserRepositoryImpl__AotRepository`**
25+
26+
Excerpt from: `target/spring-aot/main/sources/example/springdata/cassandra/UserRepositoryImpl__AotRepository.java`
27+
28+
[source,java]
29+
----
30+
@Generated
31+
public class UserRepositoryImpl__AotRepository extends AotRepositoryFragmentSupport {
32+
private final CassandraOperations operations;
33+
34+
public UserRepositoryImpl__AotRepository(CassandraOperations operations,
35+
RepositoryFactoryBeanSupport.FragmentCreationContext context) {
36+
// …
37+
}
38+
39+
public User findUserByIdIn(long id) {
40+
Object[] args = new Object[1];
41+
args[0] = potentiallyConvertBindingValue(id);
42+
SimpleStatement query = SimpleStatement.newInstance("SELECT * from users where user_id in(?)", args);
43+
44+
ExecutableSelectOperation.TerminatingResults<User> select = operations.query(query).as(User.class);
45+
return select.oneValue();
46+
}
47+
48+
public User findUserByUsername(String username) {
49+
Query query = Query.query(Criteria.where("username").is(username));
50+
51+
ExecutableSelectOperation.TerminatingSelect<User> select = operations.query(User.class).matching(query);
52+
return select.oneValue();
53+
}
54+
}
55+
----
56+
57+
== Metadata
58+
59+
**`UserRepository.json`**
60+
61+
Excerpt from: `target/spring-aot/main/resources/example/springdata/cassandra/UserRepository.json`
62+
63+
[source,json]
64+
----
65+
{
66+
"name": "example.springdata.cassandra.UserRepository",
67+
"module": "Cassandra",
68+
"type": "IMPERATIVE",
69+
"methods": [
70+
{
71+
"name": "findUserByIdIn",
72+
"signature": "public abstract example.springdata.cassandra.User example.springdata.cassandra.UserRepository.findUserByIdIn(long)",
73+
"query": {
74+
"query": "SELECT * from users where user_id in(?)"
75+
}
76+
},
77+
{
78+
"name": "findUserByUsername",
79+
"signature": "public abstract example.springdata.cassandra.User example.springdata.cassandra.UserRepository.findUserByUsername(java.lang.String)",
80+
"query": {
81+
"query": "SELECT * FROM users WHERE uname=?"
82+
}
83+
},
84+
{
85+
"name": "save",
86+
"signature": "org.springframework.data.cassandra.repository.support.SimpleCassandraRepository",
87+
"fragment": {
88+
"interface": "org.springframework.data.cassandra.repository.support.SimpleCassandraRepository",
89+
"fragment": "org.springframework.data.cassandra.repository.support.SimpleCassandraRepository"
90+
}
91+
}
92+
]
93+
}
94+
----

cassandra/aot-optimization/pom.xml

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,17 @@
33
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
44
<modelVersion>4.0.0</modelVersion>
55

6-
<artifactId>spring-data-cassandra-aot-optimization-example</artifactId>
7-
86
<parent>
97
<groupId>org.springframework.data.examples</groupId>
108
<artifactId>spring-data-cassandra-examples</artifactId>
119
<version>4.0.0-SNAPSHOT</version>
12-
<relativePath>../pom.xml</relativePath>
1310
</parent>
1411

12+
<artifactId>spring-data-cassandra-aot-optimization</artifactId>
1513
<name>Spring Data Cassandra - AOT Optimization Example</name>
16-
<description>Sample project showing the usage of Spring Data Cassandra AOT
17-
Repositories.
18-
</description>
1914

2015
<dependencies>
2116

22-
<dependency>
23-
<groupId>org.springframework.data</groupId>
24-
<artifactId>spring-data-cassandra</artifactId>
25-
</dependency>
26-
2717
<dependency>
2818
<groupId>${project.groupId}</groupId>
2919
<artifactId>spring-data-cassandra-example-utils</artifactId>
@@ -55,4 +45,5 @@
5545
</plugin>
5646
</plugins>
5747
</build>
48+
5849
</project>

cassandra/aot-optimization/src/main/java/example/springdata/cassandra/User.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import org.springframework.data.cassandra.core.mapping.Column;
2525
import org.springframework.data.cassandra.core.mapping.PrimaryKey;
2626
import org.springframework.data.cassandra.core.mapping.Table;
27-
import org.springframework.data.geo.Point;
2827

2928
import com.datastax.oss.driver.api.core.data.UdtValue;
3029

@@ -48,7 +47,6 @@ public class User {
4847

4948
Address current;
5049
List<Address> previous;
51-
Point point;
5250

5351
@CassandraType(type = CassandraType.Name.UDT, userTypeName = "address") UdtValue alternative;
5452

jdbc/aot-optimization/README.adoc

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
= Spring Data JDBC - Ahead of Time Repository Optimization Example
2+
3+
The project shows the usage of AOT Repositories.
4+
Ahead of Time Repositories implement query methods through code contribution and allow for debugging queries during runtime.
5+
Additionally, AOT repositories improve startup time and reduce memory consumption because AOT optimized query methods do not require reflective introspection.
6+
Each AOT repository is documented with a JSON file that describes the queries implemented by the repository.
7+
8+
== Using AOT Repositories
9+
10+
Repository AOT processing is enabled by default when using Spring Boot's AOT processing (see `pom.xml` for `spring-boot-maven-plugin` usage).
11+
AOT processing generates AOT artifacts to `target/spring-aot` and through the regular build.
12+
When using the JVM mode (not Graal Native Images), then you need to enable AOT mode on the JVM when running your application through `-Dspring.aot.enabled=true`.
13+
14+
[source,bash]
15+
----
16+
$ mvn clean package
17+
$ java -Dspring.aot.enabled=true -jar target/spring-data-jdbc-aot-optimization-4.0.0-SNAPSHOT.jar
18+
----
19+
20+
You can find more details about AOT processing in the https://docs.spring.io/spring-data/relational/reference/4.0/jdbc/aot.html[Spring Data JDBC Reference Documentation].
21+
22+
== AOT Repository
23+
24+
**`CategoryRepositoryImpl__AotRepository`**
25+
26+
Excerpt from: `target/spring-aot/main/sources/example/springdata/aot/CategoryRepositoryImpl__AotRepository.java`
27+
28+
[source,java]
29+
----
30+
@Generated
31+
public class CategoryRepositoryImpl__AotRepository extends AotRepositoryFragmentSupport {
32+
public CategoryRepositoryImpl__AotRepository(JdbcAggregateOperations operations,
33+
RowMapperFactory rowMapperFactory,
34+
RepositoryFactoryBeanSupport.FragmentCreationContext context) {
35+
super(operations, rowMapperFactory, context);
36+
}
37+
38+
public List<Category> findAllByNameContaining(String name) {
39+
Criteria criteria = Criteria.where("name").like("%" + escape(name) + "%");
40+
StatementFactory.SelectionBuilder builder = getStatementFactory().select(Category.class).filter(criteria);
41+
42+
RowMapper rowMapper = getRowMapperFactory().create(Category.class);
43+
List result = (List) builder.executeWith((sql, paramSource) -> getJdbcOperations().query(sql, paramSource, new RowMapperResultSetExtractor<>(rowMapper)));
44+
return (List<Category>) convertMany(result, Category.class);
45+
}
46+
47+
public List<Category> findWithDeclaredQuery(String name) {
48+
class ExpressionMarker{};
49+
String query = "SELECT * FROM category WHERE name = :name";
50+
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
51+
getBindableValue(ExpressionMarker.class.getEnclosingMethod(), name, 0).bind("name", parameterSource);
52+
53+
RowMapper rowMapper = getRowMapperFactory().create(Category.class);
54+
List result = (List) getJdbcOperations().query(query, parameterSource, new RowMapperResultSetExtractor<>(rowMapper));
55+
return (List<Category>) convertMany(result, Category.class);
56+
}
57+
}
58+
----
59+
60+
== Metadata
61+
62+
**`CategoryRepository.json`**
63+
64+
Excerpt from: `target/spring-aot/main/resources/example/springdata/aot/CategoryRepository.json`
65+
66+
[source,json]
67+
----
68+
{
69+
"name": "example.springdata.aot.CategoryRepository",
70+
"module": "JDBC",
71+
"type": "IMPERATIVE",
72+
"methods": [
73+
{
74+
"name": "findProjectedByNameContaining",
75+
"signature": "public abstract java.util.List<example.springdata.aot.CategoryProjection> example.springdata.aot.CategoryRepository.findProjectedByNameContaining(java.lang.String)",
76+
"query": {
77+
"query": "SELECT \"CATEGORY\".\"NAME\" AS \"NAME\", \"CATEGORY\".\"DESCRIPTION\" AS \"DESCRIPTION\" FROM \"CATEGORY\" WHERE \"CATEGORY\".\"NAME\" LIKE :name"
78+
}
79+
},
80+
{
81+
"name": "findWithDeclaredQuery",
82+
"signature": "public abstract java.util.List<example.springdata.aot.Category> example.springdata.aot.CategoryRepository.findWithDeclaredQuery(java.lang.String)",
83+
"query": {
84+
"query": "SELECT * FROM category WHERE name = :name"
85+
}
86+
},
87+
{
88+
"name": "save",
89+
"signature": "org.springframework.data.jdbc.repository.support.SimpleJdbcRepository",
90+
"fragment": {
91+
"interface": "org.springframework.data.jdbc.repository.support.SimpleJdbcRepository",
92+
"fragment": "org.springframework.data.jdbc.repository.support.SimpleJdbcRepository"
93+
}
94+
}
95+
]
96+
}
97+
----

jdbc/aot-optimization/pom.xml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,15 @@
33
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
44
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
55
<modelVersion>4.0.0</modelVersion>
6+
67
<parent>
78
<groupId>org.springframework.data.examples</groupId>
89
<artifactId>spring-data-jdbc-examples</artifactId>
910
<version>4.0.0-SNAPSHOT</version>
1011
</parent>
1112

12-
<groupId>org.example</groupId>
1313
<artifactId>spring-data-jdbc-aot-optimization</artifactId>
1414
<name>Spring Data JDBC - AOT Optimization Example</name>
15-
<description>Sample project showing the usage of Spring Data JDBC AOT
16-
Repositories.
17-
</description>
1815

1916
<build>
2017
<plugins>

jdbc/aot-optimization/src/main/java/example/springdata/aot/CategoryConfiguration.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ public ApplicationListener<?> loggingListener() {
4141

4242
return (ApplicationListener<ApplicationEvent>) event -> {
4343
if (event instanceof RelationalEvent) {
44-
new Exception().printStackTrace();
4544
System.out.println("Received an event: " + event);
4645
}
4746
};
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
#logging.level.org.springframework.data.repository.aot.generate.RepositoryContributor=trace
2-
logging.level.org.springframework.data.repository=DEBUG
32

jpa/aot-optimization/README.adoc

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
= Spring Data JPA - Ahead of Time Repository Optimization Example
2+
3+
The project shows the usage of AOT Repositories.
4+
Ahead of Time Repositories implement query methods through code contribution and allow for debugging queries during runtime.
5+
Additionally, AOT repositories improve startup time and reduce memory consumption because AOT optimized query methods do not require reflective introspection.
6+
Each AOT repository is documented with a JSON file that describes the queries implemented by the repository.
7+
8+
== Using AOT Repositories
9+
10+
Repository AOT processing is enabled by default when using Spring Boot's AOT processing (see `pom.xml` for `spring-boot-maven-plugin` usage).
11+
AOT processing generates AOT artifacts to `target/spring-aot` and through the regular build.
12+
When using the JVM mode (not Graal Native Images), then you need to enable AOT mode on the JVM when running your application through `-Dspring.aot.enabled=true`.
13+
14+
[source,bash]
15+
----
16+
$ mvn clean package
17+
$ java -Dspring.aot.enabled=true -jar target/spring-data-jpa-aot-optimization-4.0.0-SNAPSHOT.jar
18+
----
19+
20+
You can find more details about AOT processing in the https://docs.spring.io/spring-data/jpa/reference/4.0/jpa/aot.html#aot.repositories[Spring Data JPA Reference Documentation].
21+
22+
== AOT Repository
23+
24+
**`UserRepositoryImpl__AotRepository`**
25+
26+
Excerpt from: `target/spring-aot/main/sources/example/springdata/aot/UserRepositoryImpl__AotRepository.java`
27+
28+
[source,java]
29+
----
30+
@Generated
31+
public class UserRepositoryImpl__AotRepository extends AotRepositoryFragmentSupport {
32+
private final RepositoryFactoryBeanSupport.FragmentCreationContext context;
33+
34+
private final EntityManager entityManager;
35+
36+
public UserRepositoryImpl__AotRepository(EntityManager entityManager,
37+
RepositoryFactoryBeanSupport.FragmentCreationContext context) {
38+
// …
39+
}
40+
41+
public Long countUsersByLastnameLike(String lastname) {
42+
String queryString = "SELECT COUNT(u) FROM users u WHERE u.lastname LIKE :lastname ESCAPE '\\'";
43+
Query query = this.entityManager.createQuery(queryString);
44+
query.setParameter("lastname", lastname);
45+
46+
return (Long) convertOne(query.getSingleResultOrNull(), false, Long.class);
47+
}
48+
}
49+
----
50+
51+
== Metadata
52+
53+
**`UserRepository.json`**
54+
55+
Excerpt from: `target/spring-aot/main/resources/example/springdata/aot/UserRepository.json`
56+
57+
[source,json]
58+
----
59+
{
60+
"name": "example.springdata.aot.UserRepository",
61+
"module": "JPA",
62+
"type": "IMPERATIVE",
63+
"methods": [
64+
{
65+
"name": "countUsersByLastnameLike",
66+
"signature": "public abstract java.lang.Long example.springdata.aot.UserRepository.countUsersByLastnameLike(java.lang.String)",
67+
"query": {
68+
"query": "SELECT COUNT(u) FROM users u WHERE u.lastname LIKE :lastname ESCAPE '\\'"
69+
}
70+
},
71+
{
72+
"name": "count",
73+
"signature": "org.springframework.data.jpa.repository.support.QuerydslJpaPredicateExecutor",
74+
"fragment": {
75+
"interface": "org.springframework.data.jpa.repository.support.QuerydslJpaPredicateExecutor",
76+
"fragment": "org.springframework.data.jpa.repository.support.QuerydslJpaPredicateExecutor"
77+
}
78+
},
79+
{
80+
"name": "save",
81+
"signature": "org.springframework.data.jpa.repository.support.SimpleJpaRepository",
82+
"fragment": {
83+
"interface": "org.springframework.data.jpa.repository.support.SimpleJpaRepository",
84+
"fragment": "org.springframework.data.jpa.repository.support.SimpleJpaRepository"
85+
}
86+
}
87+
]
88+
}
89+
----

0 commit comments

Comments
 (0)