Mybatis和Spring结合的事物问题

Lucare 发布于 2018/05/04 11:32
阅读 875
收藏 2

Mybatis和Spring结合的时候事物应该由Spring统一管理吧,但是我看到Mybatis自己弄了个事物接口Transaction,如果要让Spring管理,那么应该实现Spring提供的某个接口,但是没有发现什么迹象。

倒是它自己弄了个接口,自己玩得不亦乐乎。完全看不出啥动静,SqlSessionTemplate也只是对SqlSession做了些控制,其中让我不理解的是,SqlSession为啥不让跨事物?这里可以看到Mybatis向上(Spring)探测了事物的状态,但是事物的相关操作没有体现出来,按理说应该在Service层切入,但是你不可能直接操控connection撒,你得调用Mybatis的实现。

所以现在有些疑惑:

1. SqlSession为啥不能跨事物?

2. Mybatis和Spring关于事物的管理,各自的职责是什么?

加载中
0
Lucare
Lucare
该评论暂时无法显示,详情咨询 QQ 群:点此入群
0
男神
男神

理论上当 Mybatis 和spring 结合的时候 Mybatis 不用再去管事务

  <bean id="txManager"
         class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
         <property name="dataSource" ref="dataSource"></property>
     </bean>

而spring是直接从数据源去做事务的控制

男神
男神
恩 我认为是的
Lucare
Lucare
那就是相当于直接操作 connection了?
0
阁楼望月
阁楼望月

第一个问题,没太懂你意思。

第二个问题:

    首先事务不是spring独有的,mybatis也有自己的事务。当一个web项目仅仅使用一个开源框架时,那就需要该框架支持事务,否则需要自己手动实现,比较麻烦。

    mybatis和spring一起使用来配置事务的时候,事务由spring控制,spring充当了容器管理和事务管理的职责,mybatis仅用于数据源获取。此时mybatis框架本身的事务是没用到的。

    【如果要让Spring管理,那么应该实现Spring提供的某个接口,但是没有发现什么迹象】这是思路是错的,spring和mybatis的事务配置,事务是由spring统一管理,spring框架本身就支持了。第二spring管理了事务大前提肯定要拿到数据库连接,而mybatis发挥的作用就是提供数据库连接。

    

阁楼望月
阁楼望月
回复 @Lucare : https://blog.csdn.net/majinggogogo/article/details/72026693
阁楼望月
阁楼望月
回复 @Lucare : spring自己就支持jdbc链接,项目如果用了spring+mybatis,然后数据库连接还是spring自己弄得,那mybatis还用的干嘛呢?那就完全没有必要用mybatis了,原本spring就支持ssh一套的
Lucare
Lucare
你说Mybatis只提供了数据库连接,但是实际上这个连接还是找Spring要的。
Lucare
Lucare
首先感谢!第一个问题相关代码已经补充,第二个问题你意思就是Spring基于连接控制事物的吧,但是Mybatis还是针对性的搞了一个 SpringManagedTransaction,用意何在?
0
Lucare
Lucare

补充下第一个问题相关的代码:

SqlSessionTemplate构造了方法的执行模板,调用SqlSessionUtils.getSqlSession方法来获取SqlSession:

public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {

    notNull(sessionFactory, "No SqlSessionFactory specified");
    notNull(executorType, "No ExecutorType specified");

    SqlSessionHolder holder = (SqlSessionHolder) getResource(sessionFactory);

    if (holder != null && holder.isSynchronizedWithTransaction()) {
      if (holder.getExecutorType() != executorType) {
        throw new TransientDataAccessResourceException("Cannot change the ExecutorType when there is an existing transaction");
      }

      holder.requested();

      if (logger.isDebugEnabled()) {
        logger.debug("Fetched SqlSession [" + holder.getSqlSession() + "] from current transaction");
      }

      return holder.getSqlSession();
    }

    if (logger.isDebugEnabled()) {
      logger.debug("Creating a new SqlSession");
    }

    SqlSession session = sessionFactory.openSession(executorType);

    // 省略若干代码..

}

如果当前SqlSessionHolder不为null,并且被事物锁定,那么从ThreadLocal中获取SqlSesion,否则创建一个新的SqlSession。

也就是要在同一个事物中才能共享SqlSession吧,为什么不能跨事物?

0
魔力猫
魔力猫

你在本地开两个数据库IDE,看看他们能否互相操作?最多也就是死锁而已。一个SqlSession就是一个独立的数据库连接,是没法互相操作的。

Lucare
Lucare
跨事物和跨数据库连接不一样吧
0
红薯官方
红薯官方

在spring里面使用MyBatis还需要另外一个项目,专门用来集成MyBatis到spring的:

http://www.mybatis.org/spring/

Lucare
Lucare
谢谢,我不是搭环境,我说的这个类就是mybatis-spring里的,你可以看看 SqlSessionTemplate这个类。
红薯官方
红薯官方
http://www.mybatis.org/spring/zh/index.html 中文文档链接。不知道你是不是需要了解这个。
0
Lucare
Lucare

仔细看了下,找到了Mybatis和Spring结合的事物关联之处:

1.  mybatis-spring中有个SqlSessionSynchronization继承了TransactionSynchronizationAdapter,用来提交或回滚,至于什么时候提交什么时候回滚,那要等Spring通知。

2. SqlSession的提交或者回滚都是针对Executor的操作,Executor又是操纵的事物Transaction(自定义接口)。针对Transaction接口操作可以方便各种个性化实现,如JDBC事物,JTA事物。

 

所以Spring管理事物只是管理什么传播特性啊,隔离级别啊,异常啊,到时候还是调用ORM的实现来具体提交或回滚,并不是它直接操作connection来完成的!

 

Lucare
Lucare
今天又跟了下,发现Spring是直接操作的Connection,AbstractPlatformTransactionManager的processCommit方法有提供相应的回调方法,不过那个时候required为false,BaseExecutor的commit和rollback并不会再调用Mybatis事物的相关方法。
0
很成立
很成立

到最后都还是事物事物的,也是醉了

0
loyal
loyal

结合需要mybatis-spring.jar所以用脚趾头想也知道事务管理在这里面托管给spring的.然后去这里面找代码就完事...

Lucare
Lucare
该评论暂时无法显示,详情咨询 QQ 群:点此入群
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部