2013-10-26 48 views
2
房产使用懒惰

财产标签休眠懒惰属性允许属性懒惰地加载为每链路:http://docs.jboss.org/hibernate/orm/3.3/reference/en-US/html/mapping.html#mapping-declaration-property在休眠

lazy(可选 - 默认为false):表明此属性 应当第一次访问实例变量时会被延迟取出。 它需要编译时字节码检测。

但是,当我试图设置为lazy =真为我的财产之一,它是不是在这个例子中懒洋洋地加载它:

Hibernate映射文件:

<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: 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=? 

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

回答

2

使用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将使用sec加载lazy属性ondary select:

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 
+0

Vlad,如果没有Maven,是否可以这样做? Maven在我们公司被禁止*:(我也尝试过使用'hibernate.enhance.enable'属性,但是没有结果 –

+0

Hibernate也提供了一个Gradle插件,用于构建时间检测。但是,您也可以使用[runtime instrumentation以及](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/orm.html#orm-jpa-setup-lcemfb)。 –

+0

这假设您使用EntityManager API而不是SessionFactory,是否正确?我在Hibernate代码中看到,使用属性在运行时也可能会发生检测,但代码仅在EntityManager工厂中引用 –

3

延迟加载只是提示您的持久性提供者。这个提示并没有提供任何保证,实体会被实际加载。

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

特别基本的属性很少会被懒惰地加载,因为它不会提高性能来延迟加载,反之则相反。

行为可能因环境而异,所以懒加载不可能可靠地进行测试。另一方面,预先加载(默认)是有保证的,并且可以进行测试。

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

+0

那么,我在我的项目中有证据显示,通过'ScrollableResult'流式传输的1M +实体上的VARCHAR(255)列急剧加载显着提高了性能。所以有时需要**来懒惰地加载基本属性。 –

+0

只要持久性提供程序接受提示并相应地修改SQL查询,就会有意义。我已经根据Pro JPA 2书籍提出了我的建议。它建议不要在基本道具上进行延迟加载,可能是因为持久性提供程序在写入本书时没有修改SQL。你有没有通过更改记录了由JPA发起的查询和没有懒惰提示?一些细节会很有趣。 – kostja

0

您使用的延迟加载<property name="title" lazy="true"/>是不正确的使用方式,因为标题不与其他对象关联。如果它被用在你的关系映射<set name="participants" table="PERSON_EVENT" inverse="true" lazy="true">那么它会给你一些性能提升。

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

如果lazy="true": - 这是默认配置。如果你没有提到那么休眠考虑lazy=true。当你加载Event对象那个时候子对象Person没有加载。您需要额外的数据库调用来获取地址对象。如果您致电event.getPerson(),那么数据库查询将触发并返回结果。新的数据库调用。

在一次测试中设置假<set name="participants" table="PERSON_EVENT" inverse="false" lazy="true">,然后看看你的输出查询