Hibernate整合进spring

本文详细介绍了在使用Hibernate框架时如何处理事务,包括独立使用Hibernate时通过过滤器管理事务的方法,以及在Spring框架中集成Hibernate后的多种事务管理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 零丁应用hibernate处理惩罚事物

底本只用hibernate开辟,从而可以省了DAO层实现数据库接见和跨数据库,也可以对代码进行更好的封装,当我们web中零丁应用hibernate时,我们须要零丁的处理惩罚hibernate的事务,我是应用filter来对事务进行把握的:

零丁应用hibernate应用filter进行事务把握:

HibernateSessionFilter.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public  class  HibernateSessionFilter implements  Filter {
  
     public  void  destroy() {
         
     }
  
     public  void  doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws  IOException,
             ServletException {
         Session session = HibernateUtils.openSession();
         Transaction tx = null ;
         try  {
             tx = session.beginTransaction();
             chain.doFilter(request, response);
             tx.commit();
         } catch  (Exception e) {
             if  (tx != null ) {
                 tx.rollback();
             }
             throw  new  RuntimeException(e);
         } finally  {
             HibernateUtils.closeAndRemoveSession();
         }
     }
  
     public  void  init(FilterConfig arg0) throws  ServletException {
     }
  
  }

web.xml

1
2
3
4
5
6
7
8
9
10
<filter>
   <filter-name>hibernateSessionFilter</filter-name>
   <filter- class > syx.jpkc.filter.HibernateSessionFilter</filter- class >
  </filter>
  <filter-mapping>
   <filter-name>hibernateSessionFilter</filter-name>
   <url-pattern>*.syx</url-pattern>
   <url-pattern>*.jsp</url-pattern>
   <url-pattern>*.eve</url-pattern>
  </filter-mapping>

&#160;

我首要在servlet(*.syx,*.eve)和jsp页面(没用struts)须要和数据库操纵,所以须要应用事务处理惩罚。

上方我们还用到了一个 HibernateUtils的小对象类,首要为了获取Session对象和一点优化:

HibernateUitls.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public  class  HibernateUtils {
     private  static  Map<Thread, Session> sessionMap;
     private  static  SessionFactory sessionFactory;
     static  {
         sessionMap = new  HashMap<Thread, Session>();
         sessionFactory = new  Configuration().configure().buildSessionFactory();
     }
  
     /**
      * can only use in web filter, beause it should remove and clear resources
      * @return
      */
     public  static  Session openSession() {
         System.out.println(Thread.currentThread().getStackTrace()[ 1 ] + " run in "  + new  Date());
         Session session = sessionMap.get(Thread.currentThread());
         if  (session == null ) {
             session = sessionFactory.openSession();
             sessionMap.put(Thread.currentThread(), session);
         }
         return  session;
     }
     public  static  Session getCurrentSession() {
         return  sessionMap.get(Thread.currentThread());
     }
  
     public  static  void  closeAndRemoveSession() {
         System.out.println(Thread.currentThread().getStackTrace()[ 1 ]+ " run in "  + new  Date()); //
         Session session = sessionMap.remove(Thread.currentThread());
         if  (session != null ) {
             session.close();
         }
     }
  }

&#160;

2 hibernate整合进spring后的事物处理惩罚

spring事物处理惩罚的体式格式有很多,详见:http://www.blogjava.net/robbie/archive/2009/04/05/264003.html

介绍常用的:

spring annotation声明式的事务经管

1) 事物处理惩罚层?

比如保存一个User,可以在Service层和DAOImpl层实现:

1
2
3
4
5
6
7
8
9
10
11
12
public  void  save(User u) {
     userDAO.save(u);
  }
  
  public  void  save(User u) {
     System.out.println( "save user :"  + this );
     Session s = sessionFactory.openSession();
     s.beginTransaction();
     s.save(u);
     s.getTransaction().commit();
     s.close();
  }

假如我们还有个日记记录,没保存一个User对象,要写入日记进入数据库。

而save(log) 和 save(user)必须处在同一事务中,所以不克不及放在DAOImpl层,事务处理惩罚在Service层。

2) 一般的事务处理惩罚

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Session sess = factory.openSession();
  Transaction tx;
  try  {
      tx = sess.beginTransaction();
      //do some work
      //save(user);
      //save(log);
      ...
      tx.commit();
  } catch  (Exception e) {
      if  (tx!= null ) tx.rollback();
      throw  e;
  } finally  {
      sess.close();
  }

并且要在实现层中的save()办法中也要参加事务处理惩罚,若是出呈现异常要throws给上级处理惩罚!

并且实现层中的session必须应用openCurrentSession()获得。

1
2
Session s = sessionFactory.getCurrentSession();
  s.save(u);

3) spring annotation事务处理惩罚

Beans.xml中引入响应的xml定名空间和响应设备:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
http: //www.springframework.org/schema/tx
http: //www.springframework.org/schema/tx/spring-tx-3.0.xsd
<tx:annotation-driven transaction-manager= "txManager" />
<bean id= "txManager"  class = "org.springframework.orm.hibernate3.HibernateTransactionManager" >
   <property name= "sessionFactory"  ref= "sessionFactory"  />
</bean>
<bean id= "dataSource"
     class = "org.apache.commons.dbcp.BasicDataSource"
     destroy-method= "close" >
     <property name= "driverClassName"
         value= "¥{jdbc.driverClassName}"  />
     <property name= "url"  value= "¥{jdbc.url}"  />
     <property name= "username"  value= "¥{jdbc.username}"  />
     <property name= "password"  value= "¥{jdbc.password}"  />
</bean>
<bean id= "sessionFactory"
     class = "org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" >
     <property name= "dataSource"  ref= "dataSource"  />
     <property name= "annotatedClasses" >
         <list>
             <value>com.syx.model.User</value>
             <value>com.syx.model.Log</value>
         </list>
     </property>
     <property name= "hibernateProperties" >
         <props>
             <prop key= "hibernate.dialect" >org.hibernate.dialect.MySQLDialect</prop>
             <prop key= "hibernate.show_sql" > true </prop>
             <prop key= "current_session_context_class" >thread</prop>
         </props>
     </property>
</bean>
Save办法:
public  void  save(User u) {
     Session s = sessionFactory.getCurrentSession();
     s.save(u);
}
public  void  save(Log log) {
     Session s = sessionFactory.getCurrentSession();
     s.save(log);
}
Service层处理惩罚:
@Component( "userService"
public  class  UserService {
     UserDAO userDAO = null ;
     LogDAO logDAO = null ;
     
     public  LogDAO getLogDAO() {
         return  logDAO;
     }
     @Resource(name= "logDAOMySQLImpl"
     public  void  setLogDAO(LogDAO logDAO) {
         this .logDAO = logDAO;
     }
     @Transactional
     public  void  save(User u) {
         userDAO.save(u);
         Log log = new  Log();
         log.setMsg(u.getName() + " saved in "  + new  Date());
         logDAO.save(log);
     }
     public  UserDAO getUserDAO() {
         return  userDAO;
     }
     @Resource(name= "userDAOMySQLImpl"
     public  void  setUserDAO(UserDAO userDAO) {
         this .userDAO = userDAO;
     }
}

4) @Transactional详解

什么时辰rollback

运行期异常,非运行期异常不会触发rollback

必须uncheck (没有catch)

不管什么异常,只要你catch了,spring就会放弃经管

事务传播特点:propagation_required

propagation 默认是 REQUIRED ,意思是有我们就用现成的,没的我们就发明一个,其他具体见文档

spring xml声明式的事务经管

设备景象和annotation版本一致,只是在用@Transactional处注释调用,在beans.xml中参加如下设备:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- spring tranception xml config -->
     < aop:config >
         < aop:pointcut  id="serviceOperation"
             expression="execution(* com.syx.service..*.*(..))" />
         < aop:advisor  pointcut-ref="serviceOperation" advice-ref="txAdvice" />
     </ aop:config >
  
     < tx:advice  id="txAdvice"  transaction-manager="txManager">
         < tx:attributes >
             < tx:method  name="getUser" read-only="true" />
             < tx:method  name="save" /> <!-- 相当于在上方切面pointcut@Transactional结果 -->
         </ tx:attributes >
     </ tx:advice >
1
< span  style="font-size: medium; font-weight: bold;">3 hibernateTemplate.getSessionFactory().getCurrentSession()</ span >

我们应用spring和hibernate连络,操纵数据库最常用可能是HibernateTemplate,HibernateTemplate中集成了很多应用的办法,可惜的是没的createQuery办法,也许我们应用hibernate的时辰喜好应用Query,我们可能会封装hibernateTemplate.getSessionFactory().getCurrentSession()办法获得Session,session创建Query,这是一个办法,但你应当会获得异常 “createQuery without an active transaction”,因为应用hibernateTemplate.getSessionFactory().getCurrentSession(),你是应用的hibernate的事务经管,而你指望spring经管的事物是hibernateTemplate,所以你会提示没有打开事务的异常,解决办法:1)应用hibernate事务处理惩罚,就像上方零丁应用hibernate一样,但这也许不是你想要的。2)应用hibernateTemplate的HibernateCallBack回调:

1
2
3
4
5
6
7
8
return hibernateTemplate.executeWithNativeSession(
     new HibernateCallback< List <T>>() {
     public  List< T > doInHibernate(Session session)
     throws HibernateException, SQLException {
         return session.createQuery
         ("FROM " + entityClass.getName() + " WHERE id IN (:ids)")//
         .setParameterList("ids", idList).list();
     }

&#160;

实际上hibernateTemplate中封装的find办法也很强大,若是谙练应用完全可以调换createQuery的。

备注:

若是呈现异常:对同一个凑集处理惩罚不克不及应用2个session,这是因为getCurrentSession办法失足,导致打开一个新的session,搜检设备文件,若是应用tomcat+spring+hibernate 设备hibernate.current_session_context_class 最好为thread,固然支撑jta,设备斗劲麻烦,并且jta支撑多个sessionFactory,即可以跨数据库,斗劲强大!

若是hibernate+spring呈现session没有提友情况,应当是你让spring负责事务处理惩罚,而你有应用了hibernate的session,从而离开spring事务处理惩罚,即没的begintransaction和commit之类的操纵了。



本文转自农夫山泉别墅博客园博客,原文链接:http://www.cnblogs.com/yaowen/archive/2013/02/26/2933102.html,如需转载请自行联系原作者

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值