Kotlin Hibernate OneToOne fetchtype.LAZY立即运行所有查询

我正在进行训练,培训师正在使用Java,而我正在使用Kotlin。 到目前为止,我们在任何地方都有同样的结果,但是在这里我无法得到它的工作。

有两个实体类:

@Entity data class Student( @Id @GeneratedValue var id: Long = 0, @Column(nullable = false) var name: String = "", @OneToOne() var passport: Passport? = null ) @Entity data class Passport( @Id @GeneratedValue var id: Long = 0, @Column(nullable = false) var number: String = "" ) 

而在测试类中,我使用实体管理器来执行查询。

 @RunWith(SpringRunner::class) @SpringBootTest class StudentRepositoryTest { val logger = LoggerFactory.getLogger(this.javaClass) @Autowired lateinit var studentRepository: StudentRepository @Autowired lateinit var entityManager: EntityManager @Test fun retrieveStudentAndPasswordDetails() { val student: Student? = entityManager.find(Student::class.java, 20001L) logger.info("Student -> $student") logger.info("Passport -> `${student?.passport}") } } 

当我以这种方式运行测试时,输出如预期

 Hibernate: select student0_.id as id1_3_0_, student0_.name as name2_3_0_, student0_.passport_id as passport3_3_0_, passport1_.id as id1_1_1_, passport1_.number as number2_1_1_ from student student0_ left outer join passport passport1_ on student0_.passport_id=passport1_.id where student0_.id=? 2017-12-29 20:51:04.258 TRACE 17233 --- [ main] ohtype.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [20001] 2017-12-29 20:51:04.263 TRACE 17233 --- [ main] ohtype.descriptor.sql.BasicExtractor : extracted value ([id1_1_1_] : [BIGINT]) - [40001] 2017-12-29 20:51:04.265 TRACE 17233 --- [ main] ohtype.descriptor.sql.BasicExtractor : extracted value ([name2_3_0_] : [VARCHAR]) - [Ranga] 2017-12-29 20:51:04.266 TRACE 17233 --- [ main] ohtype.descriptor.sql.BasicExtractor : extracted value ([passport3_3_0_] : [BIGINT]) - [40001] 2017-12-29 20:51:04.267 TRACE 17233 --- [ main] ohtype.descriptor.sql.BasicExtractor : extracted value ([number2_1_1_] : [VARCHAR]) - [E123456] 2017-12-29 20:51:04.269 INFO 17233 --- [ main] i.StatisticalLoggingSessionEventListener : Session Metrics { 19949 nanoseconds spent acquiring 1 JDBC connections; 0 nanoseconds spent releasing 0 JDBC connections; 1097216 nanoseconds spent preparing 1 JDBC statements; 227119 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) } 2017-12-29 20:51:04.269 INFO 17233 --- [ main] cijhjrStudentRepositoryTest : Student -> Student(id=20001, name=Ranga, passport=Passport(id=40001, number=E123456)) 2017-12-29 20:51:04.269 INFO 17233 --- [ main] cijhjrStudentRepositoryTest : Passport -> `Passport(id=40001, number=E123456) 

这看起来非常好。 使用连接调用查询,并显示两个日志输出。

使用FetchType.LAZY

在这里,我将FetchType.LAZY添加到OneToOne注释中,该注释应该使检索护照数据等到实际需要时为止。

 @Entity data class Student( @Id @GeneratedValue var id: Long = 0, @Column(nullable = false) var name: String = "", @OneToOne(fetch = FetchType.LAZY) var passport: Passport? = null ) 

这是我看到一些意想不到的行为。

我期望的是看到查询来检索学生数据,然后记录学生数据的输出。 下一个查询来检索护照数据,最后是护照数据的日志。

当懒惰加载将被完全忽略,那么我会希望仍然看到连接,而是有2个单独的查询,这似乎使事情变得更糟,没有延迟加载。

 Hibernate: select student0_.id as id1_3_0_, student0_.name as name2_3_0_, student0_.passport_id as passport3_3_0_ from student student0_ where student0_.id=? 2017-12-29 21:03:53.401 TRACE 17380 --- [ main] ohtype.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [20001] 2017-12-29 21:03:53.411 TRACE 17380 --- [ main] ohtype.descriptor.sql.BasicExtractor : extracted value ([name2_3_0_] : [VARCHAR]) - [Ranga] 2017-12-29 21:03:53.412 TRACE 17380 --- [ main] ohtype.descriptor.sql.BasicExtractor : extracted value ([passport3_3_0_] : [BIGINT]) - [40001] Hibernate: select passport0_.id as id1_1_0_, passport0_.number as number2_1_0_ from passport passport0_ where passport0_.id=? 2017-12-29 21:03:53.413 TRACE 17380 --- [ main] ohtype.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [40001] 2017-12-29 21:03:53.415 TRACE 17380 --- [ main] ohtype.descriptor.sql.BasicExtractor : extracted value ([number2_1_0_] : [VARCHAR]) - [E123456] 2017-12-29 21:03:53.427 INFO 17380 --- [ main] i.StatisticalLoggingSessionEventListener : Session Metrics { 33422 nanoseconds spent acquiring 1 JDBC connections; 0 nanoseconds spent releasing 0 JDBC connections; 569626 nanoseconds spent preparing 2 JDBC statements; 1612599 nanoseconds spent executing 2 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) } 2017-12-29 21:03:53.427 INFO 17380 --- [ main] cijhjrStudentRepositoryTest : Student -> Student(id=20001, name=Ranga, passport=Passport(id=40001, number=E123456)) 2017-12-29 21:03:53.427 INFO 17380 --- [ main] cijhjrStudentRepositoryTest : Passport -> `Passport(id=40001, number=E123456) 

@交易注释

还有一点:当教练在测试方法上运行没有@Transacional的测试时,会抛出exception。
就我而言,我是否使用这个注解没有什么区别。