当前位置:首页 > 开发 > 编程语言 > Hibernate > 正文

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

发表于: 2013-11-16   作者:alleni123   来源:转载   浏览次数:
摘要: Session session = HibernateUtil.openSession(); Transaction tx = null; tx = session.beginTransaction(); User user=(User) session.get(User.class, 538); System.out.println(user.g
	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, 就会报出一个经典的异常。
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)


从上面的异常信息可以看出, 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会报错。


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)



这个错误我会想当然的认为, 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对象便有了。 程序正常运行。

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

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
Hibernate3开始增加了通过property节点的lazy属性,为特定的属性指定延迟加载策略,以避免实体整体
1 延迟加载策略   Hibernate 的延迟加载(lazy load)是一个被广泛使用的技术。这种延迟加载保证
Hibernae 的延迟加载是一个非常常用的技术,实体的集合属性默认会被延迟加载,实体所关联的实体默认
Hibernae 的延迟加载是一个非常常用的技术,实体的集合属性默认会被延迟加载,实体所关联的实体默认
Hibernae 的延迟加载是一个非常常用的技术,实体的集合属性默认会被延迟加载,实体所关联的实体默认
Hibernae 的延迟加载是一个非常常用的技术,实体的集合属性默认会被延迟加载,实体所关联的实体默认
Hibernate3开始增加了通过property节点的lazy属性,为特定的属性指定延迟加载策略,以避免实体整体
http://developer.51cto.com/art/201208/352795.htm 当 Hibernate 从数据库中初始化某个持久化实体
Hibernae 的延迟加载是一个非常常用的技术,实体的集合属性默认会被延迟加载,实体所关联的实体默认
为什么需要延迟加载? 因为会提高效率嘛,存在即合理,哈哈.一般设置延迟加载就是在对象关系映射上(在
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号