我们知道在hibernate中我们为了程序的严谨和规范一般会这样子写与数据库交互的部分代码如下:
Session s = null;
try {
s = sessionFactory.openSession();
s.getTransaction().begin();
s.save(user);
s.getTransaction().commit();
} catch (HibernateException e) {
e.printStackTrace();
s.getTransaction().rollback();
}finally{
if(s!=null){
s.close();
s=null;
}
这样在每一个交互中都这样写会很麻烦,Hibernate3中提供了一个HibernateTemplate实际上它是一个设计模式,来帮我们解决这样的重复性工作,(Hibernate4中却把它抛弃了)在beans.xml中的配置如下:
<bean id="hibernateTempl" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
我们观察HibernateTemplate类发现它持有sessionFactory并且封装了session的save,load等方法,所以原来的代码就变为下面了:
private HibernateTemplate hibernateTemplate;
public HibernateTemplate getHibernateTemplate(){
Return hibernateTemplate;
}
@Resource
public HibernateTemplate setHibernateTemplate(HibernateTemplate hibernateTemplate){
Return this.hibernateTemplate= hibernateTemplate;
}
public void save(User user){
hibernateTemplate.save(user);
}
那么HibernateTemplate类中的save方法是怎么实现的呢?源码如下:
public Serializable save(final Object entity) throws DataAccessException {
return executeWithNativeSession(new HibernateCallback<Serializable>() {
public Serializable doInHibernate(Session session) throws HibernateException {
checkWriteOperationAllowed(session);
return session.save(entity);
}
});
}
其中所有异常都会被封装为DataAccessException属于RuntimeException这样就统一处理一种异常。executeWithNativeSession方法原理如下:
先定义一个接口:
import org.hibernate.Session;
public interface MyHibernateCallback {
public void doInHibernate(Session s);
}
这个doInHibernate接受一个Session参数,利用Session来进行增删改查,当然接口调用者可以根据具体需要去重写这个方法接着去实现一个类来调用这个接口:
import org.hibernate.Session;
public class MyHibernateTemplate {
public void executeWithNativeSession(MyHibernateCallback callback){
Session s = null;
try{
s = getSession();
s.beginTransaction();
callback.doInHibernate(s);
s.getTransaction().commit();
}catch(Exception e){
s.getTransaction().rollback();
}finally{
//...
}
}
private Session getSession() {
return null;
}
public static void main(String[]args){
new MyHibernateTemplate().executeWithNativeSession(new MyHibernateCallback(){
public void doInHibernate(Session s) {
s.save(null);
}
});
}
}
其中executeWithNativeSession接受一个MyHibernateCallback参数这样不会写死处理程序。当然调用者就需要自己去重写接口的方法。Callback是回调也称钩子函数,很形象描述了其他地方都写好了,然后在这里伸出一个钩子callback.doInHibernate(s)。