Corrections to the Criteria chapter and add a multi-from example
This commit is contained in:
parent
1e470f9e4d
commit
500d74c35d
|
@ -64,12 +64,12 @@ The example uses `createQuery()` passing in the `Person` class reference as the
|
|||
|
||||
[NOTE]
|
||||
====
|
||||
The call to the `CriteriaQuery#select` method in this example is unnecessary because _personRoot_ will be the implied selection since we have only a single query root.
|
||||
The call to the `CriteriaQuery#select` method in this example is unnecessary because _root_ will be the implied selection since we have only a single query root.
|
||||
It was done here only for completeness of an example.
|
||||
|
||||
The `Person_.eyeColor` reference is an example of the static form of JPA Metamodel reference.
|
||||
The `Person_.name` reference is an example of the static form of JPA Metamodel reference.
|
||||
We will use that form exclusively in this chapter.
|
||||
See the documentation for the Hibernate JPA Metamodel Generator for additional details on the JPA static Metamodel.
|
||||
See the documentation for the https://docs.jboss.org/hibernate/orm/5.0/topical/html/metamodelgen/MetamodelGenerator.html[Hibernate JPA Metamodel Generator] for additional details on the JPA static Metamodel.
|
||||
====
|
||||
|
||||
[[criteria-typedquery-expression]]
|
||||
|
@ -87,7 +87,7 @@ include::{sourcedir}/CriteriaTest.java[tags=criteria-typedquery-expression-examp
|
|||
----
|
||||
====
|
||||
|
||||
In this example, the query is typed as `java.lang.Integer` because that is the anticipated type of the results (the type of the `Person#age` attribute is `java.lang.Integer`).
|
||||
In this example, the query is typed as `java.lang.String` because that is the anticipated type of the results (the type of the `Person#nickName` attribute is `java.lang.String`).
|
||||
Because a query might contain multiple references to the `Person` entity, attribute references always need to be qualified.
|
||||
This is accomplished by the `Root#get` method call.
|
||||
|
||||
|
@ -130,7 +130,7 @@ but in this case it says to select and return an __Object[]__.
|
|||
=== Selecting a wrapper
|
||||
|
||||
Another alternative to <<criteria-typedquery-multiselect>> is to instead select an object that will "wrap" the multiple values.
|
||||
Going back to the example query there, rather than returning an array of _[Person#id, Person#age]_, instead declare a class that holds these values and use that as a return object.
|
||||
Going back to the example query there, rather than returning an array of _[Person#id, Person#nickName]_, instead declare a class that holds these values and use that as a return object.
|
||||
|
||||
[[criteria-typedquery-wrapper-example]]
|
||||
.Selecting a wrapper
|
||||
|
@ -175,7 +175,7 @@ The difference here is that the type of the `javax.persistence.criteria.Criteria
|
|||
The javax.persistence.Tuple contract provides three forms of access to the underlying elements:
|
||||
|
||||
typed::
|
||||
The <<criteria-tuple-example>> example illustrates this form of access in the `tuple.get( idPath )` and `tuple.get( agePath )` calls.
|
||||
The <<criteria-tuple-example>> example illustrates this form of access in the `tuple.get( idPath )` and `tuple.get( nickNamePath )` calls.
|
||||
This allows typed access to the underlying tuple values based on the `javax.persistence.TupleElement` expressions used to build the criteria.
|
||||
positional::
|
||||
Allows access to the underlying tuple values based on the position.
|
||||
|
@ -229,7 +229,16 @@ include::{sourcedir}/CriteriaTest.java[tags=criteria-from-root-example]
|
|||
====
|
||||
|
||||
Criteria queries may define multiple roots, the effect of which is to create a cartesian product between the newly added root and the others.
|
||||
Here is an example matching all single men and all single women:
|
||||
Here is an example of cross joining `Person` and `Partner` entities;
|
||||
|
||||
[[criteria-from-multiple-root-example]]
|
||||
.Adding a root example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/CriteriaTest.java[tags=criteria-from-multiple-root-example]
|
||||
----
|
||||
====
|
||||
|
||||
[[criteria-from-join]]
|
||||
=== Joins
|
||||
|
@ -264,7 +273,7 @@ include::{sourcedir}/CriteriaTest.java[tags=criteria-from-fetch-example]
|
|||
[NOTE]
|
||||
====
|
||||
Technically speaking, embedded attributes are always fetched with their owner.
|
||||
However in order to define the fetching of _Phone#addresses_ we needed a `javax.persistence.criteria.Fetch`, because element collections are `LAZY` by default.
|
||||
However in order to define the fetching of _Phone#addresses_ we needed a `javax.persistence.criteria.Fetch` because element collections are `LAZY` by default.
|
||||
====
|
||||
|
||||
[[criteria-path]]
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
CriteriaQuery query = builder.createQuery();
|
||||
|
||||
Root<Person> men = query.from( Person.class );
|
||||
Root<Person> women = query.from( Person.class );
|
||||
|
||||
Predicate menRestriction = builder.and(
|
||||
builder.equal( men.get( Person_.gender ), Gender.MALE ),
|
||||
builder.equal( men.get( Person_.relationshipStatus ), RelationshipStatus.SINGLE )
|
||||
);
|
||||
Predicate womenRestriction = builder.and(
|
||||
builder.equal( women.get( Person_.gender ), Gender.FEMALE ),
|
||||
builder.equal( women.get( Person_.relationshipStatus ), RelationshipStatus.SINGLE )
|
||||
);
|
||||
query.where( builder.and( menRestriction, womenRestriction ) );
|
|
@ -19,12 +19,15 @@ import javax.persistence.criteria.Fetch;
|
|||
import javax.persistence.criteria.Join;
|
||||
import javax.persistence.criteria.ParameterExpression;
|
||||
import javax.persistence.criteria.Path;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.userguide.model.AddressType;
|
||||
import org.hibernate.userguide.model.Call;
|
||||
import org.hibernate.userguide.model.CreditCardPayment;
|
||||
import org.hibernate.userguide.model.Partner;
|
||||
import org.hibernate.userguide.model.Partner_;
|
||||
import org.hibernate.userguide.model.Person;
|
||||
import org.hibernate.userguide.model.Person_;
|
||||
import org.hibernate.userguide.model.Phone;
|
||||
|
@ -47,6 +50,7 @@ public class CriteriaTest extends BaseEntityManagerFunctionalTestCase {
|
|||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
Person.class,
|
||||
Partner.class,
|
||||
Phone.class,
|
||||
Call.class,
|
||||
CreditCardPayment.class,
|
||||
|
@ -114,6 +118,9 @@ public class CriteriaTest extends BaseEntityManagerFunctionalTestCase {
|
|||
|
||||
entityManager.persist( creditCardPayment );
|
||||
entityManager.persist( wireTransferPayment );
|
||||
|
||||
Partner partner = new Partner( "John Doe" );
|
||||
entityManager.persist( partner );
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -238,6 +245,12 @@ public class CriteriaTest extends BaseEntityManagerFunctionalTestCase {
|
|||
|
||||
List<Tuple> tuples = entityManager.createQuery( criteria ).getResultList();
|
||||
|
||||
for ( Tuple tuple : tuples ) {
|
||||
Long id = tuple.get( idPath );
|
||||
String nickName = tuple.get( nickNamePath );
|
||||
}
|
||||
|
||||
//or using indices
|
||||
for ( Tuple tuple : tuples ) {
|
||||
Long id = (Long) tuple.get( 0 );
|
||||
String nickName = (String) tuple.get( 1 );
|
||||
|
@ -260,6 +273,37 @@ public class CriteriaTest extends BaseEntityManagerFunctionalTestCase {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_criteria_from_multiple_root_example() {
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
String address = "Earth";
|
||||
String prefix = "J%";
|
||||
//tag::criteria-from-multiple-root-example[]
|
||||
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||
|
||||
CriteriaQuery<Tuple> criteria = builder.createQuery( Tuple.class );
|
||||
|
||||
Root<Person> personRoot = criteria.from( Person.class );
|
||||
Root<Partner> partnerRoot = criteria.from( Partner.class );
|
||||
criteria.multiselect( personRoot, partnerRoot );
|
||||
|
||||
Predicate personRestriction = builder.and(
|
||||
builder.equal( personRoot.get( Person_.address ), address ),
|
||||
builder.isNotEmpty( personRoot.get( Person_.phones ) )
|
||||
);
|
||||
Predicate partnerRestriction = builder.and(
|
||||
builder.like( partnerRoot.get( Partner_.name ), prefix ),
|
||||
builder.equal( partnerRoot.get( Partner_.version ), 0 )
|
||||
);
|
||||
criteria.where( builder.and( personRestriction, partnerRestriction ) );
|
||||
|
||||
List<Tuple> tuples = entityManager.createQuery( criteria ).getResultList();
|
||||
//end::criteria-from-multiple-root-example[]
|
||||
assertEquals(2, tuples.size());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_criteria_from_join_example() {
|
||||
|
||||
|
|
Loading…
Reference in New Issue