Java 在Hibernate中使用lazy属性

Java 在Hibernate中使用lazy属性,java,hibernate,orm,properties,lazy-loading,Java,Hibernate,Orm,Properties,Lazy Loading,hibernate中property标记的lazy属性允许按照以下链接延迟加载属性: lazy(可选-默认为false):指定此属性 应该在第一次访问实例变量时延迟获取。 它需要构建时字节码插装 但是,当我尝试为我的一个属性设置lazy=true时,在本例中,它并没有延迟加载: 休眠映射文件: <hibernate-mapping package="org.hibernate.tutorial.domain"> <class name="Event" table="E

hibernate中property标记的lazy属性允许按照以下链接延迟加载属性:

lazy(可选-默认为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>
由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=?

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

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

如果提供者认为这是一种更好的方法,那么提供者可以自由地急切地加载它们

特别是基本属性很少会被延迟加载,因为延迟加载不会提高性能,相反

行为可能因上下文而异,因此不可能可靠地测试延迟加载。另一方面,即时加载(默认)是有保证的,并且可以对其进行测试


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

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

在上述配置中。如果
lazy=“false”
:-加载事件对象时,也会加载子对象Person并将其设置为setPerson()方法。如果调用
evet.getPerson()
,则加载的数据将返回。没有新的数据库调用

如果
lazy=“true”
:-这是默认配置。如果你没有提到,那么休眠考虑<代码>懒惰=真< /代码>。加载
事件
对象时,未加载子对象Person。您需要额外调用数据库以获取地址对象。如果调用
event.getPerson()
,则此时数据库查询将激发并返回结果。刷新数据库调用

要测试一次,请将其设置为false,然后使用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>
获取实体时:

Event event = entityManager.find(Event.class, 
    eventHolder.get().getId());

LOGGER.debug("Fetched event");
assertEquals("Cluj-Napoca", event.getLocation().getCity());
Hibernate将使用辅助选择加载lazy属性:

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

在我的项目中,我有证据表明,通过
ScrollableResult
在1M+个实体上加载一个VARCHAR(255)列可以极大地提高性能。因此,有时需要延迟加载基本属性。只要持久性提供程序接受提示并相应地修改SQL查询,这是有意义的。我已经根据专业JPA2书提出了我的建议。它建议不要在基本道具上延迟加载,可能是因为持久性提供程序在编写本书时没有修改SQL。您是否记录了JPA在有无延迟提示的情况下发出的查询?一些细节会很有趣的。弗拉德,没有梅文能做到吗?Maven在我们公司被禁止:-(我也尝试过使用
hibernate.enhance.enable
属性,但没有resultHibernate也提供用于构建时检测的Gradle插件。但是,您也可以使用。这假设您使用EntityManager API而不是SessionFactory,对吗?我在hibernate代码中看到,在运行时也可以使用prop进行检测但是代码只在EntityManager Factory中引用这对EntityManager Factory或SessionFactory都有效。这没关系。只是JPA/Hibernate实体被检测了。之后,EMF或SF.Hmmm会这样使用它们。我不确定。我的意思是,从您提供的链接来看,我似乎必须使用EntityManager来使用它们运行时插装。在我的项目中,对于根本性的更改已经非常成熟,我们使用SessionFactory。因此,我尝试将
hibernate.enhancer.enableLazyInitialization
设置到我的SessionFactory中,没有结果。查看代码,该代码似乎只在EM部分引用。我有一个问题,我将尽快对其进行编辑n最新发现。谢谢
Event event = entityManager.find(Event.class, 
    eventHolder.get().getId());

LOGGER.debug("Fetched event");
assertEquals("Cluj-Napoca", event.getLocation().getCity());
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