如果未指定where子句,则条件查询将获取所有相关实体

时间:2019-01-30 10:18:28

标签: java jpa h2 jpql criteria-api

我正在尝试运行一个简单的条件查询。然而,输出节目4次的查询被执行,而不是一个单一的查询这是相当出乎意料的。

我想知道,我是否错过了域模型或条件查询中的任何约束。

下面是域模型。

enter image description here

学生

    @Entity
    public class Student {

      @Id
      @GeneratedValue
      private Long id;

      @Column(nullable = false)
      private String name;

      @OneToOne(mappedBy="student", fetch = FetchType.LAZY)
      private Passport passport;

    ...
    }

护照

@Entity
public class Passport {

    @Id
    @GeneratedValue
    private Long id;

    @Column
    private String number;

    @OneToOne
    private Student student;

}

我已使用以下条件查询来获取学生记录。 我还想提到有关关系映射的几点。

  • @ManyToMany@OneToMany关系默认为Lazy加载。
  • 我已将@OneToOne明确设置为Lazy负载。

    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));
    

以下是输出:

    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)

我假设,条件查询不遵守实体上声明的FetchType.LAZY。由于Student -> Passport1-1的关系。它很热切。

如果我添加以下where子句。

cq.where(builder.equal(root.get("id"), 10001L))

仅获取学生,而不会得到以下输出所证实的其他关系。

        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)
  

更新:插入脚本。

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);

1 个答案:

答案 0 :(得分:0)

由于您在Student实体中使用mappedby,因此它使Passport成为关系的所有者,并且在加载Student时必须对其进行加载。 一种选择是像这样使学生成为所有者:

学生映射

 @OneToOne( fetch = FetchType.LAZY)
 private Passport passport;

护照映射

@OneToOne(mappedBy="passport")
private Student student;
通过执行此操作

passport_id将被添加到学生表。如果您不能这样做,则可以将OneToOne关系设为单向(学生->护照),也可以使用NO_PROXY选项。