I am trying to run a simple criteria Query. However, the output shows 4 queries being executed instead of a single query which is quite unexpected.
I am wondering, have I missed any constraints in the Domain model or Criteria Query.
Below is the domain model.
Student
@Entity
public class Student {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String name;
@OneToOne(mappedBy="student", fetch = FetchType.LAZY)
private Passport passport;
...
}
Passport
@Entity
public class Passport {
@Id
@GeneratedValue
private Long id;
@Column
private String number;
@OneToOne
private Student student;
}
I have used the below criteria query to fetch the student records. I would also like to mention few points about the relationship mapping.
@ManyToMany
and @OneToMany
relationship is by default Lazy
Load. I have explicitly set @OneToOne
as Lazy
load.
CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<Student> cq = builder.createQuery(Student.class); Root<Student> root = cq.from(Student.class); cq.select(root); //cq.where(builder.equal(root.get("id"), 10001L)); List<Student> resultList = em.createQuery(cq).getResultList(); resultList.forEach(s -> log.info("{}",s));
Following is the output:
2019-01-30 15:34:40.883 INFO 13760 --- [ main] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory
Hibernate:
select
student0_.id as id1_4_,
student0_.name as name2_4_
from
student student0_
2019-01-30 15:34:41.436 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([id1_4_] : [BIGINT]) - [2001]
2019-01-30 15:34:41.444 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([name2_4_] : [VARCHAR]) - [Irshad]
2019-01-30 15:34:41.445 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([id1_4_] : [BIGINT]) - [2002]
2019-01-30 15:34:41.446 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([name2_4_] : [VARCHAR]) - [Ahmad]
2019-01-30 15:34:41.446 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([id1_4_] : [BIGINT]) - [2003]
2019-01-30 15:34:41.446 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([name2_4_] : [VARCHAR]) - [Sheikh]
2019-01-30 15:34:41.460 TRACE 13760 --- [ main] org.hibernate.type.CollectionType : Created collection wrapper: [com.initgrep.jpademo.student.Student.addresses#2001]
2019-01-30 15:34:41.460 TRACE 13760 --- [ main] org.hibernate.type.CollectionType : Created collection wrapper: [com.initgrep.jpademo.student.Student.courses#2001]
Hibernate:
select
passport0_.id as id1_2_1_,
passport0_.number as number2_2_1_,
passport0_.student_id as student_3_2_1_,
student1_.id as id1_4_0_,
student1_.name as name2_4_0_
from
passport passport0_
left outer join
student student1_
on passport0_.student_id=student1_.id
where
passport0_.student_id=?
2019-01-30 15:34:41.465 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [2001]
2019-01-30 15:34:41.466 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([id1_4_0_] : [BIGINT]) - [2001]
2019-01-30 15:34:41.466 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([id1_2_1_] : [BIGINT]) - [4001]
2019-01-30 15:34:41.467 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([number2_2_1_] : [VARCHAR]) - [E1001]
2019-01-30 15:34:41.467 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([student_3_2_1_] : [BIGINT]) - [2001]
2019-01-30 15:34:41.475 TRACE 13760 --- [ main] org.hibernate.type.CollectionType : Created collection wrapper: [com.initgrep.jpademo.student.Student.addresses#2002]
2019-01-30 15:34:41.476 TRACE 13760 --- [ main] org.hibernate.type.CollectionType : Created collection wrapper: [com.initgrep.jpademo.student.Student.courses#2002]
Hibernate:
select
passport0_.id as id1_2_1_,
passport0_.number as number2_2_1_,
passport0_.student_id as student_3_2_1_,
student1_.id as id1_4_0_,
student1_.name as name2_4_0_
from
passport passport0_
left outer join
student student1_
on passport0_.student_id=student1_.id
where
passport0_.student_id=?
2019-01-30 15:34:41.476 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [2002]
2019-01-30 15:34:41.477 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([id1_4_0_] : [BIGINT]) - [2002]
2019-01-30 15:34:41.477 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([id1_2_1_] : [BIGINT]) - [4002]
2019-01-30 15:34:41.477 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([number2_2_1_] : [VARCHAR]) - [E1002]
2019-01-30 15:34:41.478 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([student_3_2_1_] : [BIGINT]) - [2002]
2019-01-30 15:34:41.478 TRACE 13760 --- [ main] org.hibernate.type.CollectionType : Created collection wrapper: [com.initgrep.jpademo.student.Student.addresses#2003]
2019-01-30 15:34:41.478 TRACE 13760 --- [ main] org.hibernate.type.CollectionType : Created collection wrapper: [com.initgrep.jpademo.student.Student.courses#2003]
Hibernate:
select
passport0_.id as id1_2_1_,
passport0_.number as number2_2_1_,
passport0_.student_id as student_3_2_1_,
student1_.id as id1_4_0_,
student1_.name as name2_4_0_
from
passport passport0_
left outer join
student student1_
on passport0_.student_id=student1_.id
where
passport0_.student_id=?
2019-01-30 15:34:41.479 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [2003]
2019-01-30 15:34:41.479 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([id1_4_0_] : [BIGINT]) - [2003]
2019-01-30 15:34:41.479 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([id1_2_1_] : [BIGINT]) - [4003]
2019-01-30 15:34:41.480 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([number2_2_1_] : [VARCHAR]) - [E1003]
2019-01-30 15:34:41.480 TRACE 13760 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([student_3_2_1_] : [BIGINT]) - [2003]
2019-01-30 15:34:41.480 DEBUG 13760 --- [ main] o.h.stat.internal.StatisticsImpl : HHH000117: HQL: select generatedAlias0 from Student as generatedAlias0, time: 61ms, rows: 3
2019-01-30 15:34:41.484 INFO 13760 --- [ main] i.StatisticalLoggingSessionEventListener : Session Metrics {
170294 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
**5107615 nanoseconds spent preparing 4 JDBC statements;
5699493 nanoseconds spent executing 4 JDBC statements;**
0 nanoseconds spent executing 0 JDBC batches;
0 nanoseconds spent performing 0 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections)
I am assuming, the Criteria Query does not respect the declared FetchType.LAZY
on the entity. Since Student -> Passport
is a 1-1
relationship. It is fetched eagerly.
If I add the below where clause.
cq.where(builder.equal(root.get("id"), 10001L))
It only fetches the student and no other relationships are fetched as verified by the below output.
Hibernate:
select
student0_.id as id1_4_,
student0_.name as name2_4_
from
student student0_
where
student0_.id=10001
2019-01-30 15:43:12.662 DEBUG 5964 --- [ main] o.h.stat.internal.StatisticsImpl : HHH000117: HQL: select generatedAlias0 from Student as generatedAlias0 where generatedAlias0.id=10001L, time: 22ms, rows: 0
2019-01-30 15:43:12.665 INFO 5964 --- [ main] i.StatisticalLoggingSessionEventListener : Session Metrics {
169108 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
4718825 nanoseconds spent preparing 1 JDBC statements;
7554940 nanoseconds spent executing 1 JDBC statements;
0 nanoseconds spent executing 0 JDBC batches;
0 nanoseconds spent performing 0 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections)
UPDATE: Insert script.
INSERT INTO STUDENT(id,name) VALUES (2001, 'Irshad');
INSERT INTO STUDENT(id,name) VALUES (2002, 'Ahmad');
INSERT INTO STUDENT(id,name) VALUES (2003, 'Sheikh');
INSERT INTO PASSPORT(id, number, student_id) VALUES (4001, 'E1001', 2001);
INSERT INTO PASSPORT(id, number, student_id) VALUES (4002, 'E1002', 2002);
INSERT INTO PASSPORT(id, number, student_id) VALUES (4003, 'E1003', 2003);
since you are using mappedby
in the Student entity, it makes Passport the owner of relation and it has to be loaded when you load the Student. One option is to make Student the owner like this:
Student mapping
@OneToOne( fetch = FetchType.LAZY)
private Passport passport;
Passport mapping
@OneToOne(mappedBy="passport")
private Student student;
by doing this passport_id
will be added to student table. If that is not possible for you you can either make the OneToOne relation unidirectional(Student -> Passport) or use NO_PROXY option.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.