Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved Criteria docs #3136

Merged
merged 3 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions data-connection-jdbc/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,18 @@ dependencies {

testImplementation mnReactor.micronaut.reactor

testImplementation(mnTestResources.testcontainers.mysql)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were probably all copied from data-jdbc and this module uses only h2 and postgres so remove unused dependencies.

testImplementation(mnTestResources.testcontainers.mariadb)
testImplementation(mnTestResources.testcontainers.postgres)
testImplementation(mnTestResources.testcontainers.mssql)
testImplementation(mnTestResources.testcontainers.oracle.xe)

testCompileOnly mn.micronaut.inject.groovy

testImplementation mn.micronaut.http.netty
testRuntimeOnly mnSql.micronaut.jdbc.tomcat
testRuntimeOnly mnSql.h2
testRuntimeOnly mnSql.mariadb.java.client
testRuntimeOnly mnSql.ojdbc11
testRuntimeOnly mnSql.mysql.connector.java
testRuntimeOnly mnSql.postgresql
testRuntimeOnly mnSql.mssql.jdbc
testRuntimeOnly mn.snakeyaml

testResourcesService mnSql.mariadb.java.client
testResourcesService mnSql.ojdbc11
testResourcesService mnSql.mysql.connector.java
testResourcesService mnSql.postgresql
testResourcesService mnSql.mssql.jdbc

testImplementation libs.micronaut.testresources.client

testRuntimeOnly mnSerde.micronaut.serde.oracle.jdbc.json
}

micronaut {
Expand Down
1 change: 1 addition & 0 deletions data-jdbc/src/test/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ test-resources:
mssql:
accept-license: true
startup-timeout: 300s
image-name: mcr.microsoft.com/mssql/server:2022-latest
mariadb:
startup-timeout: 300s
mysql:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.micronaut.data.repository.jpa.criteria;

import io.micronaut.core.annotation.Internal;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.annotation.Nullable;
import jakarta.persistence.criteria.CriteriaBuilder;
Expand All @@ -37,7 +38,8 @@
* @author Denis Stepanov
* @since 3.2
*/
class SpecificationComposition {
@Internal
final class SpecificationComposition {

@NonNull
static <T> QuerySpecification<T> composed(@Nullable QuerySpecification<T> lhs, @Nullable QuerySpecification<T> rhs, Combiner combiner) {
Expand Down
1 change: 1 addition & 0 deletions data-r2dbc/src/test/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ test-resources:
mssql:
accept-license: true
startup-timeout: 300s
image-name: mcr.microsoft.com/mssql/server:2022-latest
mariadb:
startup-timeout: 300s
mysql:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ class SqlServerHibernateTransactionSpec extends HibernateTransactionSpec impleme
"datasources.default.name" : "mymssqldb",
'jpa.default.properties.hibernate.hbm2ddl.auto' : 'create-drop',
'jpa.default.properties.hibernate.dialect' : 'org.hibernate.dialect.SQLServerDialect',
'test-resources.containers.mssql.accept-license' : 'true'
'test-resources.containers.mssql.accept-license' : 'true',
'test-resources.containers.mssql.image-name' : 'mcr.microsoft.com/mssql/server:2022-latest'
]
}

Expand Down
16 changes: 5 additions & 11 deletions src/main/docs/guide/dbc/dbcCriteriaSpecifications.adoc
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
In some cases, you need to build a query programmatically and at the runtime; for that, Micronaut Data implements a subset of Jakarta Persistence Criteria API 3.0, which can be used for Micronaut Data JDBC and R2DBC features. To utilize this feature add the following dependency:
Micronaut Criteria API for JDBC / R2DBC currently implements only a subset of the API.

dependency:jakarta.persistence:jakarta.persistence-api[]

To implement queries that cannot be defined at the compile-time Micronaut Data introduces api:data.repository.JpaSpecificationExecutor[] repository interface that can be used to extend your repository interface:

snippet::example.PersonRepository[project-base="doc-examples/jdbc-example",source="main" tags="repository",indent="0"]
To use Jakarta Criteria API you need to add an optional dependency:

Each method expects a "specification" which is a functional interface with a set of Criteria API objects intended to build a query programmatically.

Micronaut Criteria API currently implements only a subset of the API. Most of it is internally used to create queries with predicates and projections.
dependency:jakarta.persistence:jakarta.persistence-api[]

Currently, not supported JPA Criteria API features:

- Joins with custom `ON` expressions and typed join methods like `joinSet` etc
- Joins with custom `ON` expressions
- Operators dealing with an entity type and casting
- Collection operations: `isMember` etc
- Tuple result type
- Transformation expressions like toString, substring etc.
- Cases

Expand Down

This file was deleted.

25 changes: 0 additions & 25 deletions src/main/docs/guide/hibernate/hibernateSpecifications.adoc

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ Micronaut Data includes different variations of specification executor interface
|*Interface*
|*Description*

|api:data.repository.JpaSpecificationExecutor[]
|api:data.repository.jpa.JpaSpecificationExecutor[]
|The default interface for querying, deleting and updating data

|api:data.repository.async.AsyncJpaSpecificationExecutor[]
|api:data.repository.jpa.async.AsyncJpaSpecificationExecutor[]
|The async version of the specifications repository

|api:data.repository.reactive.ReactiveStreamsJpaSpecificationExecutor[]
|api:data.repository.jpa.reactive.ReactiveStreamsJpaSpecificationExecutor[]
|The reactive streams - `Publisher<>` version of the specifications repository

|api:data.repository.reactive.ReactorJpaSpecificationExecutor[]
|api:data.repository.jpa.reactive.ReactorJpaSpecificationExecutor[]
|The Reactor version of the specifications repository

|api:data.repository.kotlin.CoroutineJpaSpecificationExecutor[]
|api:data.repository.jpa.kotlin.CoroutineJpaSpecificationExecutor[]
|The Kotlin version of the interface that is using coroutines

|===
|===
1 change: 1 addition & 0 deletions src/main/docs/guide/shared.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ The following sections describe shared concepts of all Micronaut Data modules:
- <<querying, Querying>> - define a repository method to access your data
- <<dataUpdates, Data access>> - data access operations
- <<transactions, Transactions>> - transactional access support
- <<criteriaSpecifications, Jakarta Criteria API>> - using criteria to write queries
7 changes: 7 additions & 0 deletions src/main/docs/guide/shared/criteriaSpecifications.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
In some cases, you need to build a query programmatically and at the runtime; for that, Micronaut Data supports Jakarta Persistence Criteria API 3.0.

To implement queries that cannot be defined at the compile-time Micronaut Data introduces api:data.repository.JpaSpecificationExecutor[] repository interface that can be used to extend your repository interface:

snippet::example.PersonRepository[project-base="doc-examples/jdbc-example",source="main" tags="repository",indent="0"]

Each method expects a "specification" which is a functional interface with a set of Criteria API objects intended to build a query programmatically.
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,7 @@ snippet::example.PersonRepositorySpec[project-base="doc-examples/jdbc-example",s
NOTE: The examples use compile-known values, and in this case, it would be better to create custom repository methods which would come with compile-time generates queries and eliminate runtime overhead.
It's recommended to use criteria only for dynamic queries where the query structure is not known at the build-time.

Pagination with JOINS cannot be properly implemented with limiting the results for tabular SQL results, because of that Micronaut Data will execute two queries:

- 1. Fetching a page of entity IDs
- 2. Fetching a complete entity with JOINed associations
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
Micronaut Data includes different variations of specification executor interface intended to be used with async or reactive repositories.

.Builtin Variations of `JpaSpecificationExecutor` repository interface
[cols=2*]
|===
|*Interface*
|*Description*

|api:data.repository.jpa.JpaSpecificationExecutor[]
|The default interface for querying, deleting and updating data

|api:data.repository.jpa.async.AsyncJpaSpecificationExecutor[]
|The async version of the specifications repository

|api:data.repository.jpa.reactive.ReactiveStreamsJpaSpecificationExecutor[]
|The reactive streams - `Publisher<>` version of the specifications repository

|api:data.repository.jpa.reactive.ReactorJpaSpecificationExecutor[]
|The Reactor version of the specifications repository

|api:data.repository.jpa.kotlin.CoroutineJpaSpecificationExecutor[]
|The Kotlin version of the interface that is using coroutines

|===

.Each variation supports different Criteria specifications
[cols=2*]
|===
|*Interface*
|*Description*

|api:data.repository.jpa.criteria.PredicateSpecification[]
|A simple interface that is producing `Predicate` using the `Root` and `CriteriaBuilder`

|api:data.repository.jpa.criteria.QuerySpecification[]
|The same as `PredicateSpecification` which also includes `CriteriaQuery`

|api:data.repository.jpa.criteria.DeleteSpecification[]
|The same as `PredicateSpecification` which also includes `CriteriaDelete`

|api:data.repository.jpa.criteria.UpdateSpecification[]
|The same as `PredicateSpecification` which also includes `CriteriaUpdate`

|api:data.repository.jpa.criteria.CriteriaQueryBuilder[]
|The builder of `CriteriaQuery` using `CriteriaBuilder`

|api:data.repository.jpa.criteria.CriteriaUpdateBuilder[]
|The builder of `CriteriaUpdate` using `CriteriaBuilder`

|api:data.repository.jpa.criteria.CriteriaDeleteBuilder[]
|The builder of `CriteriaDelete` using `CriteriaBuilder`

|===
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ q.select(customer.get(Customer_.name))
.where(cb.equal(item.get(Item_.product).get(Product_.productType), "printer"));
----

Note that as of this writing you cannot use Micronaut Data annotations (those found in the io.micronaut.data.annotation package) to generate static JPA metadata, the only supported way is to use Jakarta Persistence annotations (located in the `jakarta.persistence` package) in combination with Hibernate JPA Static Metamodel Generator which will generate the metamodel even if at runtime you do not actually use Hibernate, but instead use Micronaut Data JDBC.

To configure the metamodel generator simply add the following dependency to the annotation processor classpath:

dependency:hibernate-jpamodelgen[groupId="org.hibernate.orm", scope="annotationProcessor"]

NOTE: The Hibernate 6 version of `hibernate-jpamodelgen-jakarta` is required because prior versions of Hibernate are still using the `javax.persistence` package.
For Kotlin, add the dependency in https://docs.micronaut.io/4.4.3/guide/#kaptOrKsp[kapt or ksp scope], and for Groovy add it in compileOnly scope.

NOTE: The generator supports only Jakarta Persistence annotation (located in the `jakarta.persistence` package), it's not possible to use Micronaut Data annotations (those found in the io.micronaut.data.annotation package) to generate static JPA metadata.

And we need to include the generated classes on the Java classpath to have them accessible:

Example for Gradle builds:
Expand Down
15 changes: 8 additions & 7 deletions src/main/docs/guide/toc.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
introduction:
title: Introduction
repository: Repository
repository: Repository
whatsNew: What's New?
breaks: Breaking Changes
releaseHistory: Release History
Expand Down Expand Up @@ -31,6 +31,13 @@ shared:
deletes: Deleting
timestamps: Entity Timestamps
entityEvents: Entity Events
criteriaSpecifications:
title: Repositories with Jakarta Criteria API
criteriaExecuteQuery: Querying
criteriaExecuteUpdate: Updating
criteriaExecuteDelete: Deleting
otherRepositoryVariations: Different repository variations
typeSafeJava: Type-Safe Java queries
transactions:
title: Transactions
programmaticTransactions: Programmatic Transactions
Expand All @@ -51,7 +58,6 @@ hibernate:
hibernateExplicitQueries: Explicit queries
hibernateNativeQueries: Native queries
hibernateProcedures: Procedures
hibernateSpecifications: JPA specifications
hibernateReactive: Micronaut Data Hibernate Reactive
dbc:
title: Micronaut Data JDBC and R2DBC
Expand All @@ -73,11 +79,6 @@ dbc:
pessimisticLocking: Pessimistic Locking
dbcCriteriaSpecifications:
title: Repositories with Criteria API
criteriaExecuteQuery: Querying
criteriaExecuteUpdate: Updating
criteriaExecuteDelete: Deleting
otherRepositoryVariations: Other repository variations
typeSafeJava: Type-Safe Java queries
sqlMapping:
title: Mapping Entities
sqlAnnotations: SQL Annotations
Expand Down
Loading