在Hibernate中使用lazy作为属性

hibernate中属性标记的lazy属性允许根据链接懒惰地加载属性: http : //docs.jboss.org/hibernate/orm/3.3/reference/en-US/html/mapping.html#mapping-declaration -属性

lazy(可选 – 默认为false):指定在首次访问实例变量时应该懒惰地获取此属性。 它需要构建时字节码检测。

但是,当我尝试为我的一个属性设置lazy = true时,它不会在此示例中懒惰地加载它:

Hibernate映射文件:

             

程序:

 public static void main(String[] args) { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Event event = (Event) session.get(Event.class, 135L); session.getTransaction().commit(); System.out.println(event); HibernateUtil.getSessionFactory().close(); } 

由hibernate生成的查询:

 Hibernate: select event0_.EVENT_ID as EVENT1_0_0_, event0_.EVENT_DATE as EVENT2_0_0_, event0_.title as title0_0_ from EVENTS event0_ where event0_.EVENT_ID=? 

请帮助我理解懒惰在这种情况下为什么不起作用?

使用Hibernate 5, 可以使用字节码增强轻松完成 。

首先,您需要添加以下Maven插件:

  org.hibernate.orm.tooling hibernate-enhance-maven-plugin ${hibernate.version}    true   enhance     

然后,您可以使用@Basic(fetch = FetchType.LAZY)简单地注释您的实体属性:

 @Entity(name = "Event") @Table(name = "event") public class Event extends BaseEntity { @Type(type = "jsonb") @Column(columnDefinition = "jsonb") @Basic(fetch = FetchType.LAZY) private Location location; public Location getLocation() { return location; } public void setLocation(Location location) { this.location = location; } } 

当您获取实体时:

 Event event = entityManager.find(Event.class, eventHolder.get().getId()); LOGGER.debug("Fetched event"); assertEquals("Cluj-Napoca", event.getLocation().getCity()); 

Hibernate将使用辅助选择加载惰性属性:

 SELECT e.id AS id1_0_0_ FROM event e WHERE e.id = 1 -- Fetched event SELECT e.location AS location2_0_ FROM event e WHERE e.id = 1 

延迟加载只是对持久性提供程序的一个提示。 此提示不提供实体将实际加载的任何保证。

如果提供商确定这是更好的方法,则提供商可以自由地加载它们。

特别是基本属性很少会被懒散地加载,因为它不会提升性能来加载它们,而是相反。

行为可能因上下文而异,因此无法可靠地测试延迟加载。 另一方面,预期加载(默认)是可以保证的并且可以进行测试。

编辑如果你只是想看到延迟加载的影响 – 当延迟加载的属性是与其他实体或LOB的关系时,更有可能发生延迟加载。

使用延迟加载是不正确的使用方法,因为title与其他对象没有关联。 如果在你的关系映射中使用它那么它会给你一些性能提升。

在上面的配置中。 如果lazy="false" : – 当你加载Event对象时,子对象Person也被加载并设置为setPerson()方法。 如果你调用evet.getPerson()然后加载数据返回。 没有新的数据库调用。

如果lazy="true" : – 这是默认配置。 如果你没有提到那么hibernate考虑lazy=true 。 当您加载Event对象时,未加载子对象Person。 您需要额外调用数据库才能获取地址对象。 如果调用event.getPerson()则该时间数据库查询将触发并返回结果。 新鲜数据库调用。

要测试一次设置为false 然后查看输出查询