Hibernate 的get与load方法的区别

很多时候,大家愿意说hibernate的性能差问题,其实每个技术都其精秒之处,现在将小弟对hibernate中get() load()方法的区别做一些分析:

get 立即加载

load 延迟加载

但到底立即或延迟加载的是什么?这是值得细细分析的问题。

下面以分销商(Distributor)、客户(Customer)的一对多关系来举例分析

1.Distributor.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">
<hibernate-mapping
package="entity">

<class name="Distributor" table="distributor">
<id name="id">
<generator class="uuid.hex"/>
</id>
<property name="name"/>
<property name="no"/>
<set name="cs" lazy="true">
<key column="d_id"></key>
<one-to-many class="Customer"/>
</set>
</class>
</hibernate-mapping>

2.Customer.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">
<hibernate-mapping
package="entity">
<class name="Customer" table="customer">
<id name="id">
<generator class="uuid.hex"/>
</id>
<property name="name"/>
<property name="age"/>
<many-to-one name="distributor" class="Distributor"></many-to-one>
</class>
</hibernate-mapping>

3.QueryTest.java
public class QueryTest {
public static void main(String[] args) {
Configuration cfg = new Configuration().configure();
SessionFactory sf = cfg.buildSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
Distributor d = (Distributor) session.load(Distributor.class, "297e467b30eaf6110130eaf6151b0001");
session.getTransaction().commit();
session.close();
System.out.println("d.getName=>"+d.getName());
for(Customer c: d.getCs()){
System.out.println(c.getName());
}
}
}

4:分析:
4.1 QueryTest.java中,我们使用load方法查询出的数据,并没有在session关闭前取出数据,而是将取数据的代码写在session.close()之后,也就是说当session关闭后,我们再测试,是不是能够到到它里面的数据,结果显示:即取不到Distributor对象的基本信息,也取不到关系对象的Customer集合信息(这个当然取不到了,连Distributor都取不到就没有可能取到集合)
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
log4j:WARN Please initialize the log4j system properly.
Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:132)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:174)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at entity.Distributor_$$_javassist_1.getName(Distributor_$$_javassist_1.java)
at QueryTest.main(QueryTest.java:30)

4.2 如果将上面的load方法改为get方法,则结果马上发生变化,结果显示:Distributor的基本信息取值没有问题,而它的关联集合中的数据无法取到。
因此,通过以上两个的测试,我们可以得出结论【load方法延迟加载,load方法在调用的时候得到的只是一个代理对象,真正去访问数据的时候才会发送sql语句去查询;get方法立即加载,当调用的时候,就已经执行了sql语句,不管是否去取值,都已经从数据中取得并放在对象当中】
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
log4j:WARN Please initialize the log4j system properly.
Hibernate: select distributo0_.id as id1_0_, distributo0_.name as name1_0_, distributo0_.no as no1_0_ from distributor distributo0_ where distributo0_.id=?
d.getName=>分销商
Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: entity.Distributor.cs, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:365)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:186)
at QueryTest.main(QueryTest.java:31)

4.3 lazy的说明:本例中的lazy本身与load get方法没有什么关系,但往往有朋友认为对于是否立即加载的对象看成是关联关系存在而造成的差异,这里明确说明【没有】。对于延迟加载的lazy参数,在这儿从编程的角度作一个说明:一般编程中,我们为了图方便,可以直接在配置文件中配置lazy="false",让其立即加载,但这样会影响性能,可能有时候我们并不需要它的关联集合,却已经把sql发送过去了,业内的朋友的编程经验是:不做关联关系,在程序中自己控制关联关系,这种想法是可以的,但就有些out了,本身hibernate自己已经有了这样一个关联查询机制,现在却自己实现,还不如不用;个人的经验:lazy在配置文件中设置为true,使其延迟加载,而需要立即加载的时候,则使用局部立即加载,这样,在性能上就可以大大的优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值