1.
HibernateTemplate template = (MyHibernateTemplate) context.getBean( " hibernateTemplate " );
Emp emp = (Emp) template.load(Emp. class , new Long( 7369 ));
long no = emp.getEmpno();
log.info( " empno = " + no);
String name = emp.getEname();
log.info( " Empname = " + name);
上面的代码在一般情况执行到String name=emp.getEname();的时候就会抛出org.hibernate.LazyInitializationException的异常,这个是容易理解的,因为Emp emp = (Emp) template.load(Emp.class, new Long(7369));默认是延迟数据的加载的,HibernateTemplate在执行完Emp emp = (Emp) template.load(Emp.class, new Long(7369));这句话后打开的session就关闭了。因而你在执行 String name = emp.getEname();这条语句时,这个时候才会向数据查询,但是这个时候session已经关闭,因而会出现上面的异常。为什么session会关闭呢?看一下Hibernate的源码就知道了,其核心代码是下面这段:
Assert.notNull(action, " Callback object must not be null " );
Session session = getSession();
boolean existingTransaction = SessionFactoryUtils.isSessionTransactional(session, getSessionFactory());
if (existingTransaction) {
logger.debug( " Found thread-bound Session for HibernateTemplate " );
}
FlushMode previousFlushMode = null ;
try {
previousFlushMode = applyFlushMode(session, existingTransaction);
enableFilters(session);
Session sessionToExpose = (exposeNativeSession ? session : createSessionProxy(session));
Object result = action.doInHibernate(sessionToExpose);
flushIfNecessary(session, existingTransaction);
return result;
}
catch (HibernateException ex) {
throw convertHibernateAccessException(ex);
}
catch (SQLException ex) {
throw convertJdbcAccessException(ex);
}
catch (RuntimeException ex) {
// Callback code threw application exception...
throw ex;
}
finally {
if (existingTransaction) {
logger.debug( " Not closing pre-bound Hibernate Session after HibernateTemplate " );
disableFilters(session);
if (previousFlushMode != null ) {
session.setFlushMode(previousFlushMode);
}
}
else {
// Never use deferred close for an explicitly new Session.
if (isAlwaysUseNewSession()) {
SessionFactoryUtils.closeSession(session);
}
else {
SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());
}
}
}
}
因为HibernateTemplate是通过方法的回调执行你所操作的方法的。对应的话你调用的方法对应的就是
Object result = action.doInHibernate(sessionToExpose);这一句当这些代码执行完后,最后看finally语句,应该可以看到,如果existingTransaction这个变量为false,也就是说,你所进行的操作没有进行事务管理的,最总就关闭session了。大家可以代码跟踪一下就知道existingTransaction一般情况下的值就是为false的。那么我们就可以考虑让existingTransaction为true,也就是让自己的操作进入事务管理,这个时候session就不会关闭了,除非你自己关闭。比如我们进行一个junit测试如下:
import java.util.Iterator;
import java.util.Set;
import junit.framework.TestCase;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.orm.hibernate3.MyHibernateTemplate;
import org.springframework.orm.hibernate3.MySessionFactoryUtils;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.orm.hibernate3.SessionHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;
public class TestSession extends TestCase
... {
Logger log = Logger.getLogger(TestSession.class);
SessionFactory sessionFactory = null;
Session session = null;
ApplicationContext bf = null;
public void testSession()
...{
MyHibernateTemplate template = (MyHibernateTemplate) bf
.getBean("hibernateTemplate");
Emp emp = (Emp) template.load(Emp.class, new Long(7369));
long no = emp.getEmpno();
log.info("empno = " + no);
String name = emp.getEname();
log.info("Empname = " + name);
Dept dept = (Dept) template.load(Dept.class, new Long(30));
log.info("dept no =" + dept.getDeptno());
log.info("dept name=" + dept.getDname());
Set set = dept.getEmps();
for (Iterator iterator = set.iterator(); iterator.hasNext();)
...{
Emp emp3 = (Emp) iterator.next();
log.info("empname = " + emp3.getEname());
}
}
@Override
protected void setUp() throws Exception
...{
super.setUp();
bf = new ClassPathXmlApplicationContext("applicationContext.xml");
sessionFactory = (SessionFactory) bf.getBean("sessionFactory");
session = MySessionFactoryUtils.getSession(sessionFactory, true);
TransactionSynchronizationManager.bindResource(sessionFactory,
new SessionHolder(session));
}
@Override
protected void tearDown() throws Exception
...{
super.tearDown();
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager
.getResource(sessionFactory);
Session s = holder.getSession();
s.flush();
TransactionSynchronizationManager.unbindResource(sessionFactory);
MySessionFactoryUtils.closeSession(s);
sessionFactory.close();
}
}
为了明显的看到一些信息,我继承了HibernateTemplate了,在MyHibernateTemplate里重写了 public Object execute(HibernateCallback action, boolean exposeNativeSession) throws DataAccessException方法,自己添加了一些打印信息,最终输出结果如下:
2008-03-10 14:08:46,921 INFO [jimmee.cn.edu.zju.TestSession] - empno = 7369
Hibernate: select emp0_.EMPNO as EMPNO0_0_, emp0_.DEPTNO as DEPTNO0_0_, emp0_.ENAME as ENAME0_0_, emp0_.JOB as JOB0_0_, emp0_.MGR as MGR0_0_, emp0_.HIREDATE as HIREDATE0_0_, emp0_.SAL as SAL0_0_, emp0_.COMM as COMM0_0_ from SCOTT.EMP emp0_ where emp0_.EMPNO=?
2008-03-10 14:08:47,015 INFO [jimmee.cn.edu.zju.TestSession] - Empname = SMITH
2008-03-10 14:08:47,015 DEBUG [org.springframework.transaction.support.TransactionSynchronizationManager] - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@2bccb2] for key [org.hibernate.impl.SessionFactoryImpl@18bbf55] bound to thread [main]
2008-03-10 14:08:47,015 INFO [org.springframework.orm.hibernate3.MyHibernateTemplate] - session id=26578114
2008-03-10 14:08:47,015 INFO [org.springframework.orm.hibernate3.MyHibernateTemplate] - factory id=org.hibernate.impl.SessionFactoryImpl@18bbf55
2008-03-10 14:08:47,015 DEBUG [org.springframework.transaction.support.TransactionSynchronizationManager] - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@2bccb2] for key [org.hibernate.impl.SessionFactoryImpl@18bbf55] bound to thread [main]
2008-03-10 14:08:47,015 INFO [org.springframework.orm.hibernate3.MyHibernateTemplate] - existingTransaction = true
2008-03-10 14:08:47,015 DEBUG [org.springframework.orm.hibernate3.MyHibernateTemplate] - Found thread-bound Session for HibernateTemplate
2008-03-10 14:08:47,015 DEBUG [org.springframework.orm.hibernate3.MyHibernateTemplate] - Not closing pre-bound Hibernate Session after HibernateTemplate
2008-03-10 14:08:47,015 INFO [jimmee.cn.edu.zju.TestSession] - dept no =30
Hibernate: select dept0_.DEPTNO as DEPTNO1_0_, dept0_.DNAME as DNAME1_0_, dept0_.LOC as LOC1_0_ from SCOTT.DEPT dept0_ where dept0_.DEPTNO=?
2008-03-10 14:08:47,031 INFO [jimmee.cn.edu.zju.TestSession] - dept name=SALES
Hibernate: select emps0_.DEPTNO as DEPTNO1_, emps0_.EMPNO as EMPNO1_, emps0_.EMPNO as EMPNO0_0_, emps0_.DEPTNO as DEPTNO0_0_, emps0_.ENAME as ENAME0_0_, emps0_.JOB as JOB0_0_, emps0_.MGR as MGR0_0_, emps0_.HIREDATE as HIREDATE0_0_, emps0_.SAL as SAL0_0_, emps0_.COMM as COMM0_0_ from SCOTT.EMP emps0_ where emps0_.DEPTNO=?
2008-03-10 14:08:47,046 INFO [jimmee.cn.edu.zju.TestSession] - empname = BLAKE
2008-03-10 14:08:47,046 INFO [jimmee.cn.edu.zju.TestSession] - empname = WARD
2008-03-10 14:08:47,046 INFO [jimmee.cn.edu.zju.TestSession] - empname = TURNER
2008-03-10 14:08:47,046 INFO [jimmee.cn.edu.zju.TestSession] - empname = ALLEN
2008-03-10 14:08:47,046 INFO [jimmee.cn.edu.zju.TestSession] - empname = MARTIN
2008-03-10 14:08:47,046 INFO [jimmee.cn.edu.zju.TestSession] - empname = JAMES
2008-03-10 14:08:47,046 DEBUG [org.springframework.transaction.support.TransactionSynchronizationManager] - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@2bccb2] for key [org.hibernate.impl.SessionFactoryImpl@18bbf55] bound to thread [main]
2008-03-10 14:08:47,062 DEBUG [org.springframework.transaction.support.TransactionSynchronizationManager] - Removed value [org.springframework.orm.hibernate3.SessionHolder@2bccb2] for key [org.hibernate.impl.SessionFactoryImpl@18bbf55] from thread [main]
2008-03-10 14:08:47,062 INFO [org.springframework.orm.hibernate3.SessionFactoryUtils] - Closing Hibernate Session
2008-03-10 14:08:47,062 DEBUG [org.springframework.orm.hibernate3.SessionFactoryUtils] - Closing Hibernate Session
2008-03-10 14:08:47,062 INFO [org.springframework.orm.hibernate3.SessionFactoryUtils] - session id=26578114
2008-03-10 14:08:47,078 INFO [org.springframework.orm.hibernate3.SessionFactoryUtils] - Closed Hibernate Session
2008-03-10 14:08:47,078 INFO [org.hibernate.impl.SessionFactoryImpl] - closing