hibernate
IntelliJ IDEA
默认情况下,Hibernate实体会被急切地检索;也就是说,当您从数据库检索对象时,也同时检索任何依赖对象。对于售票处,检索Person对象也将检索其相关的票务对象和事件对象。
这可能是一个相当昂贵、耗时的操作。对于一个真正的票务系统,它可能包含数千个事件,每个事件都可能有数万张票,检索所有这些对象没有多大意义。
值得庆幸的是,Hibernate允许您延迟加载对象;也就是说,查询将在需要时发生。
下图显示了如何对Ticket对象执行此操作。如果将票证和事件设置为延迟加载,那么在检索Person对象时,只有在尝试访问票证集引用或事件引用时,才会从数据库加载它们的票证和事件。
要使对象延迟加载,需要向Hibernate映射中的相关属性添加lazy='proxy'属性。
为了证明这一点,无论何时访问person的Ticket对象,如果仍然打开show_sql属性,就会看到Hibernate记录查询。
然而,有可能做得更好来证明这一点。通过记录创建事件对象的时间,您可以确定它们是在正确的时间创建的。下图显示了可以对Event类进行的一些临时更改。
如果您不熟悉AtomicInteger类,简单地说,它是一个整数的持有者,可以通过线程安全的方式访问这个整数进行读写。
通过添加静态计数器,可以在适当的时候全局引用并检查它。值得强调的是,这不是一个好的设计,也不是特别安全的代码,但是在这里,它可以很好地证明这一点。
只需要在无参数构造函数中增加计数器;因为这是Hibernate在构造事件时使用的惟一构造函数。
下图显示了如何确定事件是延迟加载的。
可以看看延迟加载的日志:
关于这个测试,你应该注意几点。首先,调用Hibernate之前将constructedInstances 变量重置为零,即使在类初始化时将其设置为零。这是因为Hibernate会在测试开始时重新创建这些对象,以确保映射是正确的。
如果system . out.println被删除,并且检索到的Person对象从未被引用,编译器可能会完全删除检索,因为Person对象永远不会被使用。
检索Person对象之后,计数器应该仍然为零,即使Hibernate已经从数据库中收集了Person,而且似乎可以访问票据集。
一旦获取了票据并引用了它们的事件对象,就会创建事件。这可以通过事件构造函数增加计数器来验证。
您应该能够看到用测试打印的行与Hibernate日志记录交织在一起,以便从数据库中提取事件细节。如果从Tickets.hbm.xml映射中删除lazy属性,测试将会失败,正如您所期望的那样。