hibernate中属性标记的lazy属性允许根据链接懒惰地加载属性:http://docs.jboss.org/hibernate/orm/3.3/reference/en-US/html/mapping.html#mapping-declaration-property
lazy(可选 - 默认为false):指定此属性 首次访问实例变量时应该懒惰地获取。 它需要构建时字节码检测。
但是当我试图为我的一个属性设置lazy = true时,它不会在这个例子中懒得加载它:
Hibernate Mapping文件:
<hibernate-mapping package="org.hibernate.tutorial.domain">
<class name="Event" table="EVENTS" select-before-update="true">
<id name="id" column="EVENT_ID">
<generator class="native" />
</id>
<property name="date" type="timestamp" column="EVENT_DATE" />
<property name="title" lazy="true"/>
<set name="participants" table="PERSON_EVENT" inverse="true">
<key column="EVENT_ID" />
<many-to-many column="PERSON_ID" class="Person" />
</set>
</class>
</hibernate-mapping>
程序:
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=?
请帮助我理解为什么懒惰在这种情况下不起作用?
答案 0 :(得分:5)
使用Hibernate 5,this can be done easily using bytecode enhancement。
首先,您需要添加以下Maven插件:
<plugin>
<groupId>org.hibernate.orm.tooling</groupId>
<artifactId>hibernate-enhance-maven-plugin</artifactId>
<version>${hibernate.version}</version>
<executions>
<execution>
<configuration>
<enableLazyInitialization>true</enableLazyInitialization>
</configuration>
<goals>
<goal>enhance</goal>
</goals>
</execution>
</executions>
</plugin>
然后,您只需使用@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
答案 1 :(得分:3)
延迟加载只是对持久性提供程序的一个提示。此提示不提供实体将实际加载的任何保证。
如果提供商确定这是一种更好的方法,则提供商可以随意加载它们。
特别是基本属性很少会被懒散地加载,因为它不会提升性能来加载它们,而是相反。
行为可能因上下文而异,因此无法可靠地测试延迟加载。另一方面,预期加载(默认)是可以保证的并且可以进行测试。
编辑如果您只是想看到延迟加载的影响 - 当延迟加载的属性与其他实体或LOB的关系时,更有可能发生延迟加载。
答案 2 :(得分:0)
使用<property name="title" lazy="true"/>
的延迟加载不是正确的使用方式,因为title与其他对象无关。如果它在您的关系映射<set name="participants" table="PERSON_EVENT" inverse="true" lazy="true">
中使用,那么它将为您带来一些性能提升。
在上面的配置中。如果lazy="false"
: - 当您加载Event对象时,子对象Person也被加载并设置为setPerson()方法。如果您调用evet.getPerson()
,则会返回已加载的数据。没有新的数据库调用。
如果lazy="true"
: - 这是默认配置。如果你不提,那么hibernate会考虑lazy=true
。当您加载Event
对象时,未加载子对象Person。您需要额外调用数据库才能获取地址对象。如果您调用event.getPerson()
,则该时间数据库查询将触发并返回结果。新鲜的数据库电话。
要测试一次设置为false <set name="participants" table="PERSON_EVENT" inverse="false" lazy="true">
,然后查看输出查询