简体   繁体   中英

Criteria Query fetches all the related entities if the where clause is not specified

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM