4

hibernate 中属性标签的惰性属性允许根据链接延迟加载属性:http: //docs.jboss.org/hibernate/orm/3.3/reference/en-US/html/mapping.html#mapping-declaration -财产

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

但是,当我尝试为我的一个属性设置lazy=true 时,在此示例中它并没有延迟加载它:

休眠映射文件:

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

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

4

3 回答 3

6

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

首先,您需要添加以下 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
于 2016-07-04T12:12:17.070 回答
3

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

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

尤其是基本属性很少会延迟加载,因为延迟加载它们不会提高性能,而是相反。

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

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

于 2013-10-26T18:14:05.727 回答
0

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

在上面的配置中。If 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"> ,然后查看您的输出查询

于 2013-10-26T18:16:47.937 回答