事务
一个使用 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 对象:
<beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <propertyname="dataSource"ref="dataSource"/> </bean>
指定的 DataSource 一般可以是你使用 Spring 的任意 JDBCDataSource。这包含了连接 池和通过 JNDI 查找获得的 DataSource。
要注意, 为事务管理器指定的 DataSource 必须和用来创建SqlSessionFactoryBean 的 是同一个数据源,否则事务管理器就无法工作了。
容器管理事务
如果你正使用一个 JEE 容器而且想让 Spring参与到容器管理事务(Container managedtransactions,CMT,译者注)中,那么
Spring 应该使用 JtaTransactionManager 或它的容器指定的子类来配置。做这件事情的最方便的方式是用 Spring 的事务命名空间:
<tx:jta-transaction-manager/>
在这种配置中,MyBatis 将会和其它由 CMT 配置的 Spring事务资源一样。Spring 会自动 使用任意存在的容器事务,在上面附加一个 SqlSession。如果没有开始事务,或者需要基 于事务配置,Spring会开启一个新的容器管理事务。
注 意 , 如 果 你 想 使 用 CMT , 而 不 想 使 用 Spring 的 事 务管 理 , 你 就 必 须 配 置 SqlSessionFactoryBean 来使用基本的 MyBatis 的ManagedTransactionFactory 而不是其 它任意的 Spring 事务管理器:
<beanid="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean"> <propertyname="dataSource"ref="dataSource"/> <propertyname="transactionFactory"> <beanclass="org.apache.ibatis.transaction.managed.ManagedTransactionFactory"/> </property> </bean>
编程式事务管理
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 来处理事务。
DefaultTransactionDefinitiondef=newDefaultTransactionDefinition(); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); TransactionStatus status= txManager.getTransaction(def); try{ userMapper.insertUser(user); } catch(MyException ex){ txManager.rollback(status); throwex; } txManager.commit(status);
注意这段代码展示了一个映射器,但它也能和 SqlSession 一起使用。