Session和Transaction安全撤离现场

Session和Transaction安全撤离现场

    
     周末和 MIKE 吃饭的时候,他询问,上次提说的问题,什么时候能写出来。“对SessionTransaction的处理,最好单独实现一个模板类来统一做”

 

温故 居于常规的HibernateDAO代码。例子做一个Create操作

 1 public   void  createPerson()  {
 2        Session session = null;
 3        Transaction tran = null;
 4        try {
 5            // Obtain Session
 6            Configuration config = new Configuration()
 7                    .configure();
 8            SessionFactory sessionFactory = config.buildSessionFactory();
 9            session = sessionFactory.openSession();
10
11            // Obtain Transaction
12            tran = session.beginTransaction();
13
14            // Obtain Person
15            Person person = new Person();
16            person.setPersonName("IBM");
17            person.setPersonEmail("[email protected]");
18            person.setPersonSex("M");
19            // Create Person
20            session.save(person);
21            session.flush();
22            tran.commit(); // 这步安全执行后,Person真正写入数据库
23        }
 catch (HibernateException e) {
24            e.printStackTrace();
25            if (tran != null{
26                try {
27                    tran.rollback();
28                }
 catch (HibernateException ex) {
29                    ex.printStackTrace();
30                }

31            }

32        }
 finally {
33            if (session != null)
34                session.close();
35        }

36    }

37


     这段代码怎么样? 假如这样的代码会出现在你的每一个DAO的每一个方法里面(除了SessionFactory建议写成一个方法,因为你只需要一个实例)你能接受吗?只说try catch 就够你写的。

如果代码在每个地方都出现。那么我想就可以抽离出来。做成一个模板。具体该怎么做呢?今天我打算谈三种比较成熟的做法。

      采用Spring提供的模板功能

      自己实现一个功能相当的模板

      其他可借鉴的实现

 

采用Spring提供的模板功能

看代码:

         

 1       public   class  PersonHibernateDao  extends  HibernateDaoSupport  implements  IPersonDao {
 2
 3         public void saveUser(Person person){
 4
 5              getHibernateTemplate().saveOrUpdate(person);
 6
 7         }

 8
 9     }

10

 

     比起上面的代码,现在简单多了吧?其实该做的事情都做了,只不过是被Spring封装起来了。大致跟踪一下SpringSourceCode的实现。

1)   在抽象类HibernateDaoSupport中有一个方法getHibernateTemplate()。通过getHibernateTemplate()得到一个HibernateTemplate对象。

2)   HibernateDaoSupport中有两个方法。通过他们来的到这个 HibernateTemplate对象

 1 public   final   void  setSessionFactory(SessionFactory sessionFactory)  {
 2
 3  this.hibernateTemplate = createHibernateTemplate(sessionFactory);
 4
 5}

 6
 7 protected  HibernateTemplate createHibernateTemplate(SessionFactory sessionFactory)  {
 8
 9     return new HibernateTemplate(sessionFactory);
10
11}

12


3)   找到saveOrUpdate()方法

 1 public   void  saveOrUpdate( final  Object entity)  throws  DataAccessException  {
 2   execute(new HibernateCallback() // call execute() 
 3// 这里使用了匿名内部类 来实现doInHibernate()
 4     public Object doInHibernate(Session session) throws HibernateException {
 5               checkWriteOperationAllowed(session);
 6               session.saveOrUpdate(entity);
 7               return null;
 8          }

 9     }
true);
10}

11

4)   核心的实现就在HibernateTemplate里面。篇幅原因,我就不Copy全部的代码了


1 public  Object execute(HibernateCallback action,  boolean  exposeNativeSession)  throws  DataAccessException  {
2
3}

4


这里,帮你做了SessionTransaction的封装。让你可以免去烦琐无谓的try catch finally 和相关操作。在Spring中基本上采用容器处理事务。这样在事务的处理上也达到了统一性。    

    到这里,感觉还不错吧? 要是你没有打算使用Spring呢?这种优势不就没有了吗?那到未必,既然都有得“抄袭”拉!就自己弄一个吧!

 

自己实现一个功能相当的模板

不容易描述清楚,就用简单的代码来说明吧。

 

 1 package  com.goingmm.test;
 2 import  org.hibernate.HibernateException;
 3 import  org.hibernate.Session;
 4 import  org.hibernate.SessionFactory;
 5 import  org.hibernate.Transaction;
 6 import  org.hibernate.cfg.Configuration;
 7 //  HibernateTemplate 来集中处理 Session和Transaction
 8
 9 public   class  HibernateTemplate  {
10     public static SessionFactory sessionFactory = null;
11public void perform(HibernateCallback callback) {
12         Session session = null;
13         Transaction tx = null;
14         try {
15              if (sessionFactory != null)
16                   session = sessionFactory.openSession();
17              else
18                   session = initSessionFactory().openSession();
19              tx = session.beginTransaction();
20// 把对象纳入Hibernate管理是在execute里面实现的
21              callback.execute(session);
22              session.flush();
23              tx.commit();
24         }
 catch (HibernateException e) {
25              try {
26                   tx.rollback();
27              }
 catch (Throwable t) {
28              }

29              throw new RuntimeException(e);
30         }
 finally {
31              try {
32                   if(session != null)
33session.close();
34              }
 catch (HibernateException ex) {
35                   throw new RuntimeException(ex);
36              }

37         }

38     }

39// 建议用一个Servlet,在应用开始的时候Call一次 来初始化SessionFactory
40     public static SessionFactory initSessionFactory() {
41         Configuration config = new Configuration().configure();
42         sessionFactory = config.buildSessionFactory();
43         return sessionFactory;
44     }

45}

46



 

1 package  com.goingmm.test;
2 import  org.hibernate.HibernateException;
3 import  org.hibernate.Session;
4 public   interface  HibernateCallback  {
5     void execute(Session session) throws HibernateException;
6}

7
8  
9

 

 1 package  com.goingmm.test;
 2 import  org.hibernate.HibernateException;
 3 import  org.hibernate.Session;
 4
 5 public   class  PersonHibernateDao  implements  IDAO {
 6public void create(final Object person) {
 7// 这里使用了匿名内部类 来实现execute
 8new HibernateTemplate().perform(new HibernateCallback(){
 9              public void execute(Session session) throws HibernateException {
10//标题不是说Session要撤离吗?    这里撤离了,就等于没有使用Hibernate 呵呵!
11session.save(person); 
12         }

13     }
);
14     }

15}

16

 

 1 package  com.goingmm.test;
 2 import  com.goingmm.bean.Person;
 3 public   class  UseHibernateTemplateTest {
 4     public static void main(String[] args) {
 5         IDAO dao = new PersonHibernateDao();
 6         Person person = new Person();
 7         person.setPersonName("IBM");
 8         person.setPersonEmai("[email protected]");
 9         person.setPersonSex("M");
10         dao.create(person);
11     }

12}

13


     上面的DAO实现还有代码风格都不推荐大家学习。实现一个优秀的DAO框架没这么简单。这种做法我没有在真实项目中检验过,不确定,会不会有其他问题。因为这里我只是为了简单的表述HibernateTemplate思想的实现。只要理解了这种思想,相信你能写出更好更完美的实现。如果有更好的主意或者建议请Email告诉我。

 

其他可借鉴的实现

     《深入浅出Hibernate》采用hibernatesynchronizer生成基础代码的方式,架构自己的持久层。作者自己实现了一个相似功能的HibernateTemplateHibernateCallback接口。有兴趣的话可以去研究一下。

     这种能直接生成基础代码的方式很不错。比起Spring我还是觉得麻烦了很多。而且我也还没时间去全面玩这个插件(据说,有提供一些成熟的模板方式生成,我只玩过默认的生成方式)。

    

2005-12-6 SCSCHINA New Office


你可能感兴趣的:(Session和Transaction安全撤离现场)