gpt4 book ai didi

java - 在 Hibernate Component 标签中延迟加载不起作用

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:24:04 26 4
gpt4 key购买 nike

我有一个如上所示的小型 hibernate 应用程序: aaaa

BankAccount类如下:

    package in.co.way2learn;
import java.util.Set;
public class BankAccount {
private int accountNumber;
private String accountHoldersName;
private int balance;
private Address address;
private Set<String> emails;
//setters and getters
}

Address类如下:

package in.co.way2learn;

public class Address {
private String addressLine1;
private String addressLine2;
private String city;
private String country;
private int pinCode;

//setters and getters
}

BankAccount.hbm.xml文件如下:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Jul 2, 2014 3:59:34 PM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="in.co.way2learn">
<class name="BankAccount">
<id name="accountNumber" type="integer">
<generator class="assigned"/>
</id>
<property name="accountHoldersName" type="string"/>
<property name="balance" type="integer"/>
<component name="address" class="Address" lazy="true">
<property name="addressLine1"/>
<property name="addressLine2"/>
<property name="city"/>
<property name="country"/>
<property name="pinCode"/>
</component>
<set name="emails" order-by="email asc" table="bankaccount_emails">
<key column="SNo"/>
<element column="email" type="string"/>
</set>
</class>
</hibernate-mapping>

hibernate.cfg.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">
org.gjt.mm.mysql.Driver
</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.connection.url">
jdbc:mysql://localhost:3306/way2learnDB
</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLInnoDBDialect
</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>

<mapping resource="in/co/way2learn/BankAccount.hbm.xml"/>
</session-factory>
</hibernate-configuration>

现在我的问题是在我使用的组件标签中的 BankAccount.hbm.xml 文件中使用 lazy="true",当我使用 session 在 BankAccount 类上触发选择查询时.get(BankAccount.class, 1235); 它也从数据库加载地址详细信息,我用来触发选择查询的代码如下:

Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
BankAccount bankAccount=(BankAccount)session.get(BankAccount.class, 1235);
transaction.commit();
session.close();

触发的查询是

Hibernate: 
select
bankaccoun0_.accountNumber as accountN1_0_0_,
bankaccoun0_.accountHoldersName as accountH2_0_0_,
bankaccoun0_.balance as balance3_0_0_,
bankaccoun0_.addressLine1 as addressL4_0_0_,
bankaccoun0_.addressLine2 as addressL5_0_0_,
bankaccoun0_.city as city6_0_0_,
bankaccoun0_.country as country7_0_0_,
bankaccoun0_.pinCode as pinCode8_0_0_
from
BankAccount bankaccoun0_
where
bankaccoun0_.accountNumber=?

但是当我只使用 bankAccount.getAddress() 方法时,我希望地址详细信息将从数据库中延迟加载?

现在有人可以解释为什么 hibernate 急切地加载地址详细信息,以及如何延迟加载吗?

最佳答案

以下面的代码为例:-

class B {  
private C cee;

public C getCee() {
return cee;
}

public void setCee(C cee) {
this.cee = cee;
}
}

class C {
// Not important really
}

加载B之后,你可以调用getCee()获取C。但是你看,getCee()是你类的一个方法,Hibernate无法控制它。 Hibernate 不知道什么时候有人要调用 getCee()。这意味着 Hibernate 在从数据库加载 B 时必须将适当的值放入“cee”属性中。

如果为 C 启用了代理,Hibernate 可以放置一个尚未加载的 C-proxy 对象,但当有人使用它时将加载它。这为一对一提供了延迟加载。

但现在假设您的 B 对象可能有也可能没有关联的 C (constrained="false")。当特定的 B 没有 C 时,getCee() 应该返回什么?无效的。但请记住,Hibernate 在设置 B 时必须设置正确的“cee”值(因为它不知道何时有人会调用 getCee())。代理在这里没有帮助,因为代理本身已经是非空对象。

如果您的 B->C 映射是强制性的(constrained=true),Hibernate 将对 C 使用代理,从而导致延迟初始化。但是如果你允许 B 没有 C,Hibernate 只需要在加载 B 时检查 C 是否存在。但是用于检查存在的 SELECT 是低效的,因为相同的 SELECT 可能不仅检查存在,而且加载整个对象。所以延迟加载消失了。

解决方法 1:- 只需在 hdm 文件中为 @JoinColumn 添加注释或条目以供引用 private Address 地址;

解决方法 2:- 在 OneToOne 关系中添加 optional=false

此问题的其他解决方案:

最简单的一种是伪造一对多关系。这将起作用,因为集合的延迟加载比单个可空属性的延迟加载要容易得多,但通常如果您使用复杂的 JPQL/HQL 查询,此解决方案非常不方便。

另一种是使用构建时字节码检测。有关详细信息,请阅读 Hibernate 文档:19.1.7。使用惰性属性获取。请记住,在这种情况下,您必须将 @LazyToOne(LazyToOneOption.NO_PROXY) 注释添加到一对一关系中以使其变得惰性。将 fetch 设置为 LAZY 是不够的。

最后一个解决方案是使用运行时字节码检测,但它仅适用于那些在成熟的 Java EE 环境中使用 Hibernate 作为 JPA 提供程序的人(在这种情况下设置“hibernate.ejb.use_class_enhancer "为 true 应该可以解决问题:实体管理器配置)或使用 Hibernate 和配置为执行运行时织入的 Spring(这在某些较旧的应用程序服务器上可能很难实现)。在这种情况下,还需要 @LazyToOne(LazyToOneOption.NO_PROXY) 注释。

这对你有用。

关于java - 在 Hibernate Component 标签中延迟加载不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24574610/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com