【发布时间】:2019-01-30 10:18:27
【问题描述】:
我正在尝试运行一个简单的条件查询。但是,输出显示正在执行 4 个查询而不是单个查询,这是非常出乎意料的。
我想知道,我是否错过了域模型或标准查询中的任何约束。
下面是领域模型。
学生
@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的关系默认为LazyLoad。 -
我已将
@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 -> Passport 是1-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);
【问题讨论】:
-
只是为了确定:导致延迟关系被加载的不是你的
Student.toString()记录器调用的方法,对吧? -
@RobbyCornelissen 如果是由于
toString(),那么在使用where子句时应该不会产生影响。此外,toString()实现只显示学生的ID and NAME -
JPA 规范说:“LAZY 策略是对持久性提供程序运行时的提示”(即 JPA 2.0,第 11.1.37 章)。您的 JPA 实现决定了最佳方法是什么。
-
您似乎只有 3 个学生记录,ID 分别为 2001、2002 和 2003,因此当您查找 ID 为 10001 的学生时,它找不到任何记录,也没有必要加载 Passport。尝试在 where 子句中将 id 更改为 2003 以查看您获得了多少查询。
-
@RezaNasiri 我已经用插入脚本更新了这个问题。每个学生只有一本护照。我仍然按照您的建议使用不同的 ID 运行,但这没有任何区别。任何其他想法
标签: java jpa h2 criteria-api