一个使用 MyBatis-Spring 的主要原因是它允许 MyBatis 参与到 Spring 的事务管理中。而 不是给 MyBatis 创建一个新的特定的事务管理器,MyBatis-Spring 利用了存在于 Spring 中的 DataSourceTransactionManager。
一旦 Spring 的 PlatformTransactionManager 配置好了,你可以在 Spring 中以你通常的做 法来配置事务。@Transactional 注解和 AOP(Aspect-Oriented Program,面向切面编程,译 者注)样式的配置都是支持的。在事务处理期间,一个单独的 SqlSession 对象将会被创建 和使用。当事务完成时,这个 session 会以合适的方式提交或回滚。
一旦事务创建之后,MyBatis-Spring 将会透明的管理事务。在你的 DAO 类中就不需要额 外的代码了。
要 开 启 Spring 的 事 务 处 理 , 在 Spring 的 XML 配 置 文 件 中 简 单 创 建 一 个 DataSourceTransactionManager 对象:
<span class="tag" style="color: rgb(0, 0, 136);"><bean</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="atn" style="color: rgb(102, 0, 102);">id</span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="atv" style="color: rgb(0, 136, 0);">"transactionManager"</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="atn" style="color: rgb(102, 0, 102);">class</span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="atv" style="color: rgb(0, 136, 0);">"org.springframework.jdbc.datasource.DataSourceTransactionManager"</span><span class="tag" style="color: rgb(0, 0, 136);">></span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="tag" style="color: rgb(0, 0, 136);"><property</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="atn" style="color: rgb(102, 0, 102);">name</span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="atv" style="color: rgb(0, 136, 0);">"dataSource"</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="atn" style="color: rgb(102, 0, 102);">ref</span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="atv" style="color: rgb(0, 136, 0);">"dataSource"</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="tag" style="color: rgb(0, 0, 136);">/></span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="tag" style="color: rgb(0, 0, 136);"></bean></span>
指定的 DataSource 一般可以是你使用 Spring 的任意 JDBC DataSource。这包含了连接 池和通过 JNDI 查找获得的 DataSource。
要注意, 为事务管理器指定的 DataSource 必须和用来创建 SqlSessionFactoryBean 的 是同一个数据源,否则事务管理器就无法工作了。
如果你正使用一个 JEE 容器而且想让 Spring 参与到容器管理事务(Container managed transactions,CMT,译者注)中,那么 Spring 应该使用 JtaTransactionManager 或它的容 器指定的子类来配置。做这件事情的最方便的方式是用 Spring 的事务命名空间:
<span class="tag" style="color: rgb(0, 0, 136);"><tx:jta-transaction-manager</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="tag" style="color: rgb(0, 0, 136);">/></span>
在这种配置中,MyBatis 将会和其它由 CMT 配置的 Spring 事务资源一样。Spring 会自动 使用任意存在的容器事务,在上面附加一个 SqlSession。如果没有开始事务,或者需要基 于事务配置,Spring 会开启一个新的容器管理事务。
注 意 , 如 果 你 想 使 用 CMT , 而 不 想 使 用 Spring 的 事 务 管 理 , 你 就 必 须 配 置 SqlSessionFactoryBean 来使用基本的 MyBatis 的 ManagedTransactionFactory 而不是其 它任意的 Spring 事务管理器:
<span class="tag" style="color: rgb(0, 0, 136);"><bean</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="atn" style="color: rgb(102, 0, 102);">id</span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="atv" style="color: rgb(0, 136, 0);">"sqlSessionFactory"</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="atn" style="color: rgb(102, 0, 102);">class</span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="atv" style="color: rgb(0, 136, 0);">"org.mybatis.spring.SqlSessionFactoryBean"</span><span class="tag" style="color: rgb(0, 0, 136);">></span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="tag" style="color: rgb(0, 0, 136);"><property</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="atn" style="color: rgb(102, 0, 102);">name</span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="atv" style="color: rgb(0, 136, 0);">"dataSource"</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="atn" style="color: rgb(102, 0, 102);">ref</span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="atv" style="color: rgb(0, 136, 0);">"dataSource"</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="tag" style="color: rgb(0, 0, 136);">/></span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="tag" style="color: rgb(0, 0, 136);"><property</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="atn" style="color: rgb(102, 0, 102);">name</span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="atv" style="color: rgb(0, 136, 0);">"transactionFactory"</span><span class="tag" style="color: rgb(0, 0, 136);">></span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="tag" style="color: rgb(0, 0, 136);"><bean</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="atn" style="color: rgb(102, 0, 102);">class</span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="atv" style="color: rgb(0, 136, 0);">"org.apache.ibatis.transaction.managed.ManagedTransactionFactory"</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="tag" style="color: rgb(0, 0, 136);">/></span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="tag" style="color: rgb(0, 0, 136);"></property></span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="tag" style="color: rgb(0, 0, 136);"></bean></span>
MyBatis 的 SqlSession 提供指定的方法来处理编程式的事务。 但是当使用 MyBatis-Spring 时, bean 将会使用 Spring 管理的 SqlSession 或映射器来注入。 那就是说 Spring 通常是处理 事务的。
你 不 能 在 Spring 管 理 的 SqlSession 上 调 用 SqlSession.commit() , SqlSession.rollback() 或 SqlSession.close() 方 法 。 如 果 这 样 做 了 , 就 会 抛 出 UnsupportedOperationException 异常。注意在使用注入的映射器时不能访问那些方法。
无论 JDBC 连接是否设置为自动提交, SqlSession 数据方法的执行或在 Spring 事务之外 任意调用映射器方法都将会自动被提交。
如果你想编程式地控制事务,请参考 Spring 手册的 10.6 节。这段代码展示了如何手动 使用在 10.6.2 章节描述的 PlatformTransactionManager 来处理事务。
<span class="typ" style="color: rgb(102, 0, 102);">DefaultTransactionDefinition</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">def</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">new</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="typ" style="color: rgb(102, 0, 102);">DefaultTransactionDefinition</span><span class="pun" style="color: rgb(102, 102, 0);">();</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">def</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">setPropagationBehavior</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="typ" style="color: rgb(102, 0, 102);">TransactionDefinition</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">PROPAGATION_REQUIRED</span><span class="pun" style="color: rgb(102, 102, 0);">);</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="typ" style="color: rgb(102, 0, 102);">TransactionStatus</span><span class="pln" style="color: rgb(0, 0, 0);"> status </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> txManager</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">getTransaction</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="kwd" style="color: rgb(0, 0, 136);">def</span><span class="pun" style="color: rgb(102, 102, 0);">);</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">try</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">{</span><span class="pln" style="color: rgb(0, 0, 0);"> userMapper</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">insertUser</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">user</span><span class="pun" style="color: rgb(102, 102, 0);">);</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">}</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">catch</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="typ" style="color: rgb(102, 0, 102);">MyException</span><span class="pln" style="color: rgb(0, 0, 0);"> ex</span><span class="pun" style="color: rgb(102, 102, 0);">)</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">{</span><span class="pln" style="color: rgb(0, 0, 0);"> txManager</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">rollback</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">status</span><span class="pun" style="color: rgb(102, 102, 0);">);</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">throw</span><span class="pln" style="color: rgb(0, 0, 0);"> ex</span><span class="pun" style="color: rgb(102, 102, 0);">;</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">}</span><span class="pln" style="color: rgb(0, 0, 0);"> txManager</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">commit</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">status</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
注意这段代码展示了一个映射器,但它也能和 SqlSession 一起使用。