Hibernate延迟加载简单实例及分析

	Session session = HibernateUtil.openSession();

Transaction tx = null;

tx = session.beginTransaction();

User user=(User) session.get(User.class, 538);

System.out.println(user.getId());

tx.commit();

session.close();


System.out.println(user.getName());


Hibernate在使用get方法时,当程序运行到
User user=(User) session.get(User.class, 538);
就会直接提取出User对象,也就是向数据库发送了select语句。

get方法直接获取实例, 不存在代理。

------------------
这时如果把get换成load, 就会报出一个经典的异常。
[color=red] at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:164)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:285)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
at com.lj.zhang.User_$$_javassist_0.getName(User_$$_javassist_0.java)
at com.lj.zhang.HibernateTest5_search2.main(HibernateTest5_search2.java:47)[/color]

从上面的异常信息可以看出, hibernate通过javassist生成的代理对象进行了invoke()的调用, 我猜测应该就是这里调用了javassist所生成的对象类的查询方法。
这个生成的对象class的查询方法在运行时是要通过hibernate的一系列的配置对象的,既是SessionImpl, 但是这个东西已经关闭, 所以getImplementation压根无法得到任何Session对象。 抛出异常。
--以上纯属瞎猜,具体如何还待以后看了源码才知道。


=========================分割线===============
在mapping配置文件中, 我们可以取消延迟加载 , 通过lazy=false。
<hibernate-mapping package="com.lj.zhang">
<class name="User" table="test_user" lazy="false">
当配置了lazy=false之后, 这个User对象便会在session.load()被执行时直接被实例化。 (select语句也会被执行)


		tx.commit();

session.close();


System.out.println(user.getName());
System.out.println(user.getOrders().iterator().next().getName());

于是user.getName()会被正常执行。

这里要注意的就是第二个System.out.println会报错。


[color=red]Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.lj.zhang.User.orders, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:566)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:186)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:545)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:124)
at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:180)
at com.lj.zhang.HibernateTest5_search2.main(HibernateTest5_search2.java:48)[/color]


这个错误我会想当然的认为, Order配置文件里只要也设置lazy=false,问题就会解决。
事实是这个想法很2,
在Order里面设置这个没有任何作用。
因为Order在main程序中并不是通过load获取的, 而是通过级联获取。

所以重点在一对多的主键那里的配置。也就是User.hbm.xml里面的

<set name="orders" cascade="save-update" inverse="true"   >    <!-- 级联, inverse=true表示由多的一方维持关联关系 -->
<!-- key的column告诉hibernate多的一方的foreign key -->
<!-- 这里设置为customer_id, 就会在数据库的order表里生成相应的 -->
<key column="customer_id"></key>
<one-to-many class="com.lj.zhang.Order"/>
</set>


在set节点里加入 lazy="false",
问题就解决了。

此时通过debug模式可以看到, 程序在运行到
User user=(User) session.load(User.class, 538);
的时候, 便会向数据库发送两条select查询语句。
Hibernate: select user0_.id as id1_2_0_, user0_.test_name as test2_2_0_, user0_.test_age as test3_2_0_ from test_user user0_ where user0_.id=?

Hibernate: select orders0_.customer_id as customer3_2_1_, orders0_.id as id1_0_1_, orders0_.id as id1_0_0_, orders0_.test_name as test2_0_0_, orders0_.customer_id as customer3_0_0_ from test_order orders0_ where orders0_.customer_id=?

这时User以及与之关联的Order对象便有了。 程序正常运行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值