分享

springmvc mybatis多数据源分布式事务管理

 甘甘灰 2018-08-08

      目录

    •       springmvcmybatis多数据源分布式事务管理
    •       pom依赖
    •       jtaproperties
    •       配置数据源
    •       配置SQLSessionFactory
    •       配置MapperScanner
    •       配置Jta事务
    •       实体
    •       dao
    •       XML
    •       service
    •       Junit测试
    •       完结

springmvc+mybatis多数据源分布式事务管理

最近项目用到spring多数据源以进行数据整合,可是配置上事务时,发现数据源不能进行切换, 原因是因为事务是在connection层面管理的,启用事务后,一个事务内部的connection是复用的, 所以就算AOP切了数据源字符串,但是数据源并不会被真正修改,所以决定使用atomikos进行分布式事务的管理。

pom依赖

com.atomikostransactions-jdbc<version>3.9.1javax.transactionjta1.1cglibcglib-nodep3.2.4

jta.properties

把此配置文件放入classpath路径 项目启动会自动加载 不需进行配置 com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactorycom.atomikos.icatch.console_file_name = tm.outcom.atomikos.icatch.log_base_name = tmlog com.atomikos.icatch.tm_unique_name = com.atomikos.spring.jdbc.tmcom.atomikos.icatch.console_log_level = INFO

配置数据源

为了测试这里配置2个数据源,大家可按自己项目情况配置。 注意当配置多个数据源时uniqueResourceName的value不能重复 jdbc:mysql://localhost/testroot123456jdbc:mysql://localhost/smart-ssoroot123456

配置SQLSessionFactory

指定mapper文件和实体所在路径

配置MapperScanner

指定dao文件所在包 并指定所用SQlSessionFactory

配置Jta事务

最后加上声明式注解支持 数据源和事务配置已经完成,接下来就是测试分布式事务是否可用了。

实体

为了测试方便 这里2个数据源使用的是一个实体 publicclass Student { private Integer id; private String name; private Integer age; public Integer getId() { return id; } publicvoidsetId(Integer id) { this.id = id; } public String getName() { return name; } publicvoidsetName(String name) { this.name = name; } public Integer getAge() { return age; } publicvoidsetAge(Integer age) { this.age = age; } }

dao

这里两个mapper分别在配置MapperScanner配置的包体里 package com.fk.mapperOne; import com.fk.entity.Student; import org.springframework.stereotype.Repository; @Repository public interface StudentOneMapper { void insert(Student student); }package com.fk.mapperTwo; import com.fk.entity.Student; import org.springframework.stereotype.Repository; @Repository public interface StudentTwoMapper { void insert(Student student); }

XML

insert into student(id,name,age) values (#{id},#{name},#{age}) version='1.0' encoding='UTF-8' ?> insert into student(id,name,age) values (#{id},#{name},#{age})

service

      package com.fk.service;

      import com.fk.entity.Student;
      import com.fk.mapperOne.StudentOneMapper;
      import com.fk.mapperTwo.StudentTwoMapper;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      import org.springframework.transaction.annotation.Transactional;

      @Service
      public class StudentServiceImpl {

@Autowired private StudentOneMapper studentOneMapper; @Autowired private StudentTwoMapper studentTwoMapper; @Transactional public void insert() throws Exception{ Student student = new Student(); student.setId(1); student.setName('Nancy'); student.setAge(12); studentOneMapper.insert(student); student = new Student(); student.setId(1); student.setName('Tom'); student.setAge(2); studentTwoMapper.insert(student); }

      }

Junit测试

接下来使用junit进行测试 import com.fk.service.StudentServiceImpl; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { 'classpath:/spring/spring-mvc.xml', 'classpath:/spring/spring-mybatis.xml'}) public class StudentJunit { @Autowired private StudentServiceImpl studentService; @Test public void TestInsert(){ try { studentService.insert(); } catch (Exception e) { e.printStackTrace(); } } } 先测试下是否能插入数据

可以看到2个数据库里都已经插入一条数据 接下来在测试下异常是否会回滚 @Transactionalpublicvoidinsert() throws Exception{ Student student = new Student(); student.setId(2); student.setName('Nancy'); student.setAge(12); studentOneMapper.insert(student); student = new Student(); student.setId(1); student.setName('Tom'); student.setAge(2); studentTwoMapper.insert(student); } 将第一个插入实体的ID加1,保持第二个实体不变,因为表里有设置主键,这样第二条插入时, 会出现主键重复异常,以此来测试第一条插入语句是否会回滚。

如我们所愿,主键重复,接下来看下数据是否有插入

yes!数据没有插入,则证明事务已回滚了。

完结

分布式事务的内容就是这些了,由于本人初次接触分布式事务,有不足之处还请谅解并指出,谢谢! [完整Demo](http://git.oschina.net/monsterjava/fk_demo/tree/feature_fk/)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多