论坛首页 入门技术论坛

关于hibernate联级对象缓存

浏览 2645 次
该帖已经被评为新手帖
作者 正文
   发表时间:2008-07-28  

有部门表(PxDept)和员工表(PxEmployee)关系是PxDept(1)->PxEmployee(N)

首先PxDept.hbm.xml中这样设置

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 
	Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
<hibernate-mapping>
	<class name="hibernate.bean.PxDept" table="px_dept" schema="dbo"
		catalog="test">
		<cache region="read-write"/>
		 <id name="deptId" type="integer">
			<column name="dept_id" />
			<generator class="identity" />
		</id>
		<many-to-one name="pxDept" class="hibernate.bean.PxDept"
			insert="false" update="false">
			<column name="parent_id" />
		</many-to-one>
		<property name="parentDeptId" type="integer">
			<column name="parent_id" />
		</property>
		<property name="deptName" type="string" >
			<column name="dept_name" length="256" not-null="true" />
		</property>
<set name="pxEmployees" inverse="true"  cascade="delete" batch-size="8" lazy="true">
			<cache usage="read-write"/>
			<key>
				<column name="dept_id" not-null="true" />
			</key>
			<one-to-many class="hibernate.bean.PxEmployee" />
		</set>
	</class>
</hibernate-mapping>
我使用以下查询:
(1)List list = session.createQuery("from PxDept as p1 left join fetch p1.pxEmployees").setCacheable(true).list();
(2)list = session.createQuery("from PxDept as p1 left join fetch p1.pxEmployees").setCacheable(true).list();
在(2)中的list结果是从缓存中取的,但里边PxDept对象中的关联对象pxEmployees集合是空的
下面我面又另一种方式:
将PxDept.hbm.xml中的关联关系改下
<set name="pxEmployees" inverse="true"  cascade="delete" batch-size="8" lazy="false">
			<cache usage="read-write"/>
			<key>
				<column name="dept_id" not-null="true" />
			</key>
			<one-to-many class="hibernate.bean.PxEmployee" />
		</set>
lazy="false"
(1)List list = session.createQuery("from PxDept as p1 left join fetch p1.pxEmployees").setCacheable(true).list();
(2)list = session.createQuery("from PxDept as p1 left join fetch p1.pxEmployees").setCacheable(true).list();
这会在(2)中的list 中的pxDept中的pxEmployees集合就有数据了,请问 这什么怎么回事???

 

   发表时间:2008-07-29  
怎么没人回答?
0 请登录后投票
   发表时间:2008-07-29  
猜测,仅仅是猜测:如果你用Spring作为容器,试试OpenSessionInView,看看能否在lazy=true的情况下仍能得到pxDept中的pxEmployees集合的数据?
0 请登录后投票
   发表时间:2008-07-29  
请问下,你们没有遇到过hibernate关于联级对象缓存的问题吗
0 请登录后投票
   发表时间:2008-07-29  
我想了几种可能性,但都不敢肯定。我搜索了Hibernate的官方论坛,想找到与你的问题类似的帖子,但没有找到。不过看到其它关于cache和collection有关的帖子,发觉问题不少。比如有人提交了一个缺陷:http://opensource.atlassian.com/projects/hibernate/browse/HHH-2350

建议你也到Hibernate的官方论坛(http://forum.hibernate.org/viewforum.php?f=1)里查一查有没有与你的问题类似的帖子,或者把你的问题贴上去,看看有没有人能帮你解答一下
0 请登录后投票
   发表时间:2008-07-30  

我找到了解决办法,但还是觉得奇怪

public List createQuery(String sql,Class _class,boolean cache,int page,int pageSize,String queryType,String initializeCollectin) throws HibernateException{
		Session session = openSession();
		List result = null;
		Transaction tx = null;
		try{
			tx = session.beginTransaction();
			Query query = null;
			if(DatabaseUtil.QUERY_TYPE_SQL.equalsIgnoreCase(queryType)){
				query = session.createSQLQuery(sql);
			}else{
				query = session.createQuery(sql);
			}
			if(cache){
				query.setCacheable(true).setCacheRegion(_class.getName());
			}
			if(page>=0 && pageSize>0){
				query.setFirstResult(page * pageSize);
				query.setMaxResults((page+1)* pageSize);
			}
			result = query.list();
			if(initializeCollectin!=null && result!=null && result.size()>0){
				Object entity = result.get(0);
				String method = "get" + initializeCollectin.substring(0,1).toUpperCase() + initializeCollectin.substring(1);
				try {
					Object collection = entity.getClass().getMethod(method).invoke(entity, new Object[]{});
					if(!Hibernate.isInitialized(collection)){
						Hibernate.initialize(collection);
					}
				} catch (Exception e) {
					e.printStackTrace();
				} 
			}
			tx.commit();
		}catch(HibernateException he){
			if(tx!=null) tx.rollback();
			throw he;
		}finally{
			closeSession();
		}
		return result;
	}
	/**
	 * 根据SQL进行查询
	 * @param sql
	 * @param _class
	 * @param cache
	 * @param initializeCollection
	 * @return
	 * @throws HibernateException
	 */
	public List createQuery(String sql,String initializeCollection,Class _class,boolean cache) throws HibernateException{
		return createQuery(sql,_class,cache,0,0,null,initializeCollection);
	}

 配置文件和以上相同

我执行以下代码:

(1)List list = dbUtil.createQuery("from PxDept","pxEmployees",PxDept.class,true);
(1)中的部门对象中的员工集合是存在的,因为上边的方法中有
                                       if(!Hibernate.isInitialized(collection)){
						Hibernate.initialize(collection);
					}

(2)list = dbUtil.createQuery("from PxDept","pxEmployees",PxDept.class,true);
但(2)中只有list(0)中的部门对象的员工集合是存在的,其他部门对象的员工集合还是延迟加载的
除非在上边的方法中这样写
if(initializeCollectin!=null && result!=null && result.size()>0){
				
				String method = "get" + initializeCollectin.substring(0,1).toUpperCase() + initializeCollectin.substring(1);
				try {
					Iterator iter  = result.iterator();
                                      while(iter.hasNext()){
                                      Object entity = iter.next();
					Object collection = entity.getClass().getMethod(method).invoke(entity, new Object[]{});
					if(!Hibernate.isInitialized(collection)){
						Hibernate.initialize(collection);
					}
					if(!cache) break;
                                    }
				} catch (Exception e) {
					e.printStackTrace();
				} 
			}

 也就是说,在不使用缓存的情况下,只要在session关闭之前任意加载一下部门中的员工集合,其他部门下的员工集合也会被加载

但是在用缓存的情况下,在session关闭之前必须遍历所有部门将其下的员工集合都用hibernate.initialize(pxEmployees)一下才可,

 

有点疑惑??

0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics