zoukankan      html  css  js  c++  java
  • Spring Boot(七):Mybatis 多数据源最简解决方案

    说起多数据源,一般都来解决那些问题呢,主从模式或者业务比较复杂需要连接不同的分库来支持业务。我们遇到的情况是后者,网上找了很多,大都是根据 Jpa 来做多数据源解决方案,要不就是老的 Spring 多数据源解决方案,还有的是利用 Aop 动态切换,感觉有点小复杂,其实我只是想找一个简单的多数据支持而已,折腾了两个小时整理出来,供大家参考。

    废话不多说直接上代码吧

    我们以 Mybatis Xml 版本为例,给大家展示如何如何配置多数据源。

    配置文件

    Pom 包就不贴了比较简单该依赖的就依赖,主要是数据库这边的配置:

    1. mybatis.config-location=classpath:mybatis/mybatis-config.xml

    2. spring.datasource.test1.jdbc-url=jdbc:mysql://localhost:3306/test1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true

    3. spring.datasource.test1.username=root

    4. spring.datasource.test1.password=root

    5. spring.datasource.test1.driver-class-name=com.mysql.cj.jdbc.Driver

    6. spring.datasource.test2.jdbc-url=jdbc:mysql://localhost:3306/test2?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true

    7. spring.datasource.test2.username=root

    8. spring.datasource.test2.password=root

    9. spring.datasource.test2.driver-class-name=com.mysql.cj.jdbc.Driver

    一个 test1 库和一个 test2 库,其中 test1 位主库,在使用的过程中必须指定主库,不然会报错。

    数据源配置

    1. @Configuration

    2. @MapperScan(basePackages = "com.neo.mapper.test1", sqlSessionTemplateRef = "test1SqlSessionTemplate")

    3. public class DataSource1Config {

    4. @Bean(name = "test1DataSource")

    5. @ConfigurationProperties(prefix = "spring.datasource.test1")

    6. @Primary

    7. public DataSource testDataSource() {

    8. return DataSourceBuilder.create().build();

    9. }

    10. @Bean(name = "test1SqlSessionFactory")

    11. @Primary

    12. public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource) throws Exception {

    13. SqlSessionFactoryBean bean = new SqlSessionFactoryBean();

    14. bean.setDataSource(dataSource);

    15. bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test1/*.xml"));

    16. return bean.getObject();

    17. }

    18. @Bean(name = "test1TransactionManager")

    19. @Primary

    20. public DataSourceTransactionManager testTransactionManager(@Qualifier("test1DataSource") DataSource dataSource) {

    21. return new DataSourceTransactionManager(dataSource);

    22. }

    23. @Bean(name = "test1SqlSessionTemplate")

    24. @Primary

    25. public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {

    26. return new SqlSessionTemplate(sqlSessionFactory);

    27. }

    28. }

    最关键的地方就是这块了,一层一层注入,首先创建 DataSource,然后创建 SqlSessionFactory 再创建事务,最后包装到 SqlSessionTemplate 中。其中需要指定分库的 mapper 文件地址,以及分库dao层代码

    1. @MapperScan(basePackages = "com.neo.mapper.test1", sqlSessionTemplateRef = "test1SqlSessionTemplate")

    这块的注解就是指明了扫描 dao 层,并且给 dao 层注入指定的 SqlSessionTemplate。所有 @Bean都需要按照命名指定正确。

    dao 层和 xml层

    dao 层和 xml 需要按照库来分在不同的目录,比如:test1 库 dao 层在 com.neo.mapper.test1 包下,test2 库在 com.neo.mapper.test2

    1. public interface User1Mapper {

    2. List<UserEntity> getAll();

    3. UserEntity getOne(Long id);

    4. void insert(UserEntity user);

    5. void update(UserEntity user);

    6. void delete(Long id);

    7. }

    xml 层

    1. <mapper namespace="com.neo.mapper.test1.User1Mapper" >

    2. <resultMap id="BaseResultMap" type="com.neo.model.User" >

    3. <id column="id" property="id" jdbcType="BIGINT" />

    4. <result column="userName" property="userName" jdbcType="VARCHAR" />

    5. <result column="passWord" property="passWord" jdbcType="VARCHAR" />

    6. <result column="user_sex" property="userSex" javaType="com.neo.enums.UserSexEnum"/>

    7. <result column="nick_name" property="nickName" jdbcType="VARCHAR" />

    8. </resultMap>

    9. <sql id="Base_Column_List" >

    10. id, userName, passWord, user_sex, nick_name

    11. </sql>

    12. <select id="getAll" resultMap="BaseResultMap" >

    13. SELECT

    14. <include refid="Base_Column_List" />

    15. FROM users

    16. </select>

    17. <select id="getOne" parameterType="java.lang.Long" resultMap="BaseResultMap" >

    18. SELECT

    19. <include refid="Base_Column_List" />

    20. FROM users

    21. WHERE id = #{id}

    22. </select>

    23. <insert id="insert" parameterType="com.neo.model.User" >

    24. INSERT INTO

    25. users

    26. (userName,passWord,user_sex)

    27. VALUES

    28. (#{userName}, #{passWord}, #{userSex})

    29. </insert>

    30. <update id="update" parameterType="com.neo.model.User" >

    31. UPDATE

    32. users

    33. SET

    34. <if test="userName != null">userName = #{userName},</if>

    35. <if test="passWord != null">passWord = #{passWord},</if>

    36. nick_name = #{nickName}

    37. WHERE

    38. id = #{id}

    39. </update>

    40. <delete id="delete" parameterType="java.lang.Long" >

    41. DELETE FROM

    42. users

    43. WHERE

    44. id =#{id}

    45. </delete>

    46. </mapper>

    测试

    测试可以使用 SpringBootTest,也可以放到 Controller中,这里只贴 Controller 层的使用

    1. @RestController

    2. public class UserController {

    3. @Autowired

    4. private User1Mapper user1Mapper;

    5. @Autowired

    6. private User2Mapper user2Mapper;

    7. @RequestMapping("/getUsers")

    8. public List<UserEntity> getUsers() {

    9. List<UserEntity> users=user1Mapper.getAll();

    10. return users;

    11. }

    12. @RequestMapping("/getUser")

    13. public UserEntity getUser(Long id) {

    14. UserEntity user=user2Mapper.getOne(id);

    15. return user;

    16. }

    17. @RequestMapping("/add")

    18. public void save(UserEntity user) {

    19. user2Mapper.insert(user);

    20. }

    21. @RequestMapping(value="update")

    22. public void update(UserEntity user) {

    23. user2Mapper.update(user);

    24. }

    25. @RequestMapping(value="/delete/{id}")

    26. public void delete(@PathVariable("id") Long id) {

    27. user1Mapper.delete(id);

    28. }

    29. }

    Mybatis 注解版本配置多数据源和 Xml 版本基本一致,搭建直接参考文末的示例项目。

    文章内容已经升级到 Spring Boot 2.x

    示例代码-https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mybatis

    精彩回顾:

    面试点:Java 中 hashCode() 和 equals() 的关系

    容器连接[Docker 系列-7]

    现如今的技术浪潮中,我们到底该做些什么?

    强烈推荐:

    《Java 极客技术》知识星球限时优惠,现在加入只需 50 元,仅限前 1000 名,机不可失时不再来。趁早行动吧!

    https://t.zsxq.com/J6Em2nU

    隆重介绍:

    Java 极客技术公众号,是由一群热爱 Java 开发的技术人组建成立,专注分享原创、高质量的 Java 文章。如果您觉得我们的文章还不错,请帮忙赞赏、在看、转发支持,鼓励我们分享出更好的文章。

  • 相关阅读:
    1046 Shortest Distance (20 分)(模拟)
    1004. Counting Leaves (30)PAT甲级真题(bfs,dfs,树的遍历,层序遍历)
    1041 Be Unique (20 分)(hash散列)
    1036 Boys vs Girls (25 分)(查找元素)
    1035 Password (20 分)(字符串处理)
    1044 Shopping in Mars (25 分)(二分查找)
    onenote使用小Tip总结^_^(不断更新中...)
    1048 Find Coins (25 分)(hash)
    三个故事
    领导者的举止
  • 原文地址:https://www.cnblogs.com/justdojava/p/11098173.html
Copyright © 2011-2022 走看看