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

时间:2017-12-29 20:09:10

标签: hibernate kotlin

我正在进行培训,培训师正在使用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] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [20001]
2017-12-29 20:51:04.263 TRACE 17233 --- [           main] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_1_1_] : [BIGINT]) - [40001]
2017-12-29 20:51:04.265 TRACE 17233 --- [           main] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([name2_3_0_] : [VARCHAR]) - [Ranga]
2017-12-29 20:51:04.266 TRACE 17233 --- [           main] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([passport3_3_0_] : [BIGINT]) - [40001]
2017-12-29 20:51:04.267 TRACE 17233 --- [           main] o.h.type.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] c.i.j.h.j.r.StudentRepositoryTest        : Student -> Student(id=20001, name=Ranga, passport=Passport(id=40001, number=E123456))
2017-12-29 20:51:04.269  INFO 17233 --- [           main] c.i.j.h.j.r.StudentRepositoryTest        : 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
)

这是我看到一些意外行为的地方。

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

当延迟加载完全被忽略后,我本来期望仍然看到连接,但是有两个单独的查询,这似乎使事情更糟,然后没有延迟加载。

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] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [20001]
2017-12-29 21:03:53.411 TRACE 17380 --- [           main] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([name2_3_0_] : [VARCHAR]) - [Ranga]
2017-12-29 21:03:53.412 TRACE 17380 --- [           main] o.h.type.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] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [40001]
2017-12-29 21:03:53.415 TRACE 17380 --- [           main] o.h.type.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] c.i.j.h.j.r.StudentRepositoryTest        : Student -> Student(id=20001, name=Ranga, passport=Passport(id=40001, number=E123456))
2017-12-29 21:03:53.427  INFO 17380 --- [           main] c.i.j.h.j.r.StudentRepositoryTest        : Passport -> `Passport(id=40001, number=E123456)

@Transactional annotation

其他内容:当培训师在测试方法上运行没有@Transacional的测试时,会抛出异常。
就我而言,我是否使用此注释没有任何区别。

1 个答案:

答案 0 :(得分:0)

我今天遇到了这个问题,经过大量的研究和测试(Hibernate编译时工具),我找到的解决方案是:

  • optional = false添加到我的OneToOne
  • @LazyToOne(LazyToOneOption.PROXY)添加到我的属性
  • 设置子类open,并将子类的所有属性也open

这些步骤之后,休眠状态将自动停止获取。