开发问题一:spring的事务管理问题

一:试图通过配置的方式给springMVC的控制器加事务失败

      一般而言,事务都是加在Service层的,但是爱钻牛角尖的我时常想:事务加在Controller层可不可以。我一直试图证明事务不止可以加在Service层,还可以加在Controller层,但是没有找到有力的论据来支持我这个想法,搞得我一度认为事务只能加在Service层,直到我读过spring官方文档并实践之后,我知道我的想法是对的。

    在spring-framework-reference.pdf文档中有这样一段话:

<tx:annotation-driven/> only looks for @Transactional on beans in the same application context it is defined in. This means that, if you put <tx:annotation-driven/> in a WebApplicationContext for a DispatcherServlet, it only checks for @Transactional beans in your controllers, and not your services. 

    这句话的意思是,<tx:annoation-driven/>只会查找和它在相同的应用上下文件中定义的bean上面的@Transactional注解,如果你把它放在Dispatcher的应用上下文中,它只检查控制器上的@Transactional注解,而不是你services上的@Transactional注解。

    于是,我将事务配置定义在Spring MVC的应用上下文(*-servlet.xml)中,将@Transactional注解打在Controller上,终于事务起作用了。

    综上,在Spring MVC中,事务不仅可以加在Service层,同样也可以加在Controller层(虽然不推荐这么做,但至少满足了我的好奇心

注意: Controller层只支持 @Transactional 注解式事务!

Hibernate事务原理

 HibernateJDBC进行了轻量级的对象封装,Hibernate本身在设计时并不具备事务处理功能,平时所用的Hibernate的事务,只是将底层的JDBCTransaction或者JTATransaction进行了一下封装,在外面套上TransactionSession的外壳,其实底层都是通过委托底层的JDBCJTA来实现事务的调度功能。

Connection = null;
PreparedStatement pstmt = null;
try{
con = DriverManager.getConnection(dbUrl, username, password);
//设置手工提交事务模式
con.setAutoCommit(false);
pstmt = ……;
pstmt.executeUpdate();
//提交事务
con.commit();
}catch(Exception e){
//事务回滚
con.rollback();
…..
} finally{
    …….
}

   hibernate封装完事务后con.setAutoCommit(false)所以hibernate对数据库的操作都要设置事务边界,hibernate通过tx.commit()提交事务,commit()方法里面做了session flushmode的判断如果为AUTO(默认是AUTO)则调用session.flush()持久化数据,否则即使commit也无法持久化数据

SessionFactory factory=new Configuration().configure("config/hibernate.cfg.xml").buildSessionFactory();
	Employee ee=new Employee();
	ee.setComm(1.6f);
         ee.setEname("fuck11111");
        
         Session session=factory.openSession();
	session.setHibernateFlushMode(FlushMode.MANUAL);
	Transaction tx=session.beginTransaction();
	session.save(ee);
         tx.commit();//即使commit也无法持久化数据
:spring接管事务管理后

spring为jdbc、hibernate、jta各平台提供了事务管理统一口,利用aop编程思想,声明事务管理。

详细理解请看:http://www.mamicode.com/info-detail-1248286.html

:加了opensessioninviewfilter后

由于Hibernate引入了Lazy Load特性,使得脱离Hibernate的Session周期的对象如果再想通过getter方法取到其关联对象的值,Hibernate会抛出一个LazyLoad的Exception。所以为了解决这个问题,Spring引入了这个Filter,使得Hibernate的Session的生命周期变长。

but:

由于拿到的Hibernate的Session被设置了session.setFlushMode(FlushMode.NEVER); 所以,除非你直接调用session.flush(),否则Hibernate session无论何时也不会flush任何的状态变化到数据库。但是spring事务管理器做了一些优化(只需要你将事务属性read-only为false)

HibernteTransactionManager 中会根据事务设置改变 session 的刷新方式, 具体代码参见 HibernteTransactionManager  411 行 (Spring 1.2.8)

    if (definition.isReadOnly() && txObject.isNewSessionHolder()) {  
        // Just set to NEVER in case of a new Session for this transaction.  
        session.setFlushMode(FlushMode.NEVER);  
    }  
      
    if (!definition.isReadOnly() && !txObject.isNewSessionHolder()) {  
        // We need AUTO or COMMIT for a non-read-only transaction.  
        FlushMode flushMode = session.getFlushMode();  
        if (FlushMode.NEVER.equals(flushMode)) {  
            session.setFlushMode(FlushMode.AUTO);  
            txObject.getSessionHolder().setPreviousFlushMode(flushMode);  
        }  
    }  
openSessionInView延长了session的生命周期 导致一些弊端,还是不推荐使用


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值