HibernateTemplate 理解(对Callback继续理解)
经常使用spring封装hibernate的同学,在写dao的具体实现类的时候,一般都会让dao实现类继承HibernateDaoSupport,
这样,在我们的dao实现类中就可以直接获得HibernateTemplate对象来直接使用,HibernateTemplate封装Hibernate的基本操作,
通过HibernateTemplate源码可知,我们需要给hibernateTemplate一个sessionFactory;一般都是通过spring注入
hibernateTemplate提供了一系列的CRUD方法,现在我们以get的实现来说明:
//我们实际调用的方法
public <T> T get(Class<T> entityClass, Serializable id) throws DataAccessException {
return get(entityClass, id, null);
}
//真实实现
public <T> T get(final Class<T> entityClass, final Serializable id, final LockMode lockMode)
throws DataAccessException {
return executeWithNativeSession(new HibernateCallback<T>() {
@SuppressWarnings("unchecked")
public T doInHibernate(Session session) throws HibernateException {
if (lockMode != null) {
return (T) session.get(entityClass, id, lockMode);
}
else {
return (T) session.get(entityClass, id);
}
}
});
}
//被调用方法
public <T> T executeWithNativeSession(HibernateCallback<T> action) {
return doExecute(action, false, true);
}get()方法的具体实现是doExecute()方法,在此使用的Callback,把相同的操作都封装到了doExecute()方法中,具体的实现就在get()方法中HibernateCallback中实现,通过上面的代码可以看出,我们的Callback方法doInHibernate需要一个参数session, 此参数是在doExecute方法中传入的(doExecute方法在下面描述),真正的获取值最终还是去操作session,这里就和Hibernate里操作一样,只不过此时的session的管理和事务的管理都在
doExecute()方法中来完成,我们不需要关心,我们只需要关心我们的Callback实现我们需要的逻辑。
下面我们看一下delete方法的实现:
//我们调用的方法
public void delete(Object entity) throws DataAccessException {
delete(entity, null);
}
//具体实现方法
public void delete(final Object entity, final LockMode lockMode) throws DataAccessException {
executeWithNativeSession(new HibernateCallback<Object>() {
public Object doInHibernate(Session session) throws HibernateException {
checkWriteOperationAllowed(session);
if (lockMode != null) {
session.lock(entity, lockMode);
}
session.delete(entity);
return null;
}
});
}看到吗?和get方法如出一辙,底层实现使用doExecute方法,具体实现放到自己的Callback里
再看一下复杂操作时,我们会调用execute方法,execute方法的实现:
public <T> T execute(HibernateCallback<T> action) throws DataAccessException {
return doExecute(action, false, false);
}对,不会错了把,HibernateTemplate就是使用Callback模式把所有的方法的相同实现都放到了doExecute()方法中,具体实现放到CallBack中,Callback的抽象方法需要session,得到session后和hibernate的操作一抹一样。
下面我们就来看看doExecute()方法的具体实现:
protected <T> T doExecute(HibernateCallback<T> action, boolean enforceNewSession, boolean enforceNativeSession)
throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Session session = (enforceNewSession ?
SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor()) : getSession());
boolean existingTransaction = (!enforceNewSession &&
(!isAllowCreate() || 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 =
(enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session));
//此操作以前的代码都是在管理session,处理事务
T result = action.doInHibernate(sessionToExpose);//此行调用了HibernateCallback的具体逻辑
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());
}
}
}
}代码逻辑很清晰,前半部分去获取session,管理事务,然后就是调用hibernateCallback中具体实现的逻辑,返回结果,然后做具体的事务和session管理,
针对于hibernateTemplate提供的其他方法也是一样,使用callback模式,相同的操作都放到了doExecute中
就这样hibernateTemplate屏蔽了hibernate的复杂操作,实现了封装