经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MyBatis » 查看文章
MyBatis多数据源的两种配置方式
来源:jb51  时间:2018/12/10 9:19:44  对本文有异议

前言

同一个项目有时会涉及到多个数据库,也就是多数据源。多数据源又可以分为两种情况:

1)两个或多个数据库没有相关性,各自独立,其实这种可以作为两个项目来开发。比如在游戏开发中一个数据库是平台数据库,其它还有平台下的游戏对应的数据库;

2)两个或多个数据库是master-slave的关系,比如有mysql搭建一个 master-master,其后又带有多个slave;或者采用MHA搭建的master-slave复制;

MyBatis多数据源的配置主要有两种方式:

  • 通过@MapperScan注解,对不同包下的Mapper使用不同的sqlSessionFactory
  • 通过@MapperScan注解加自定义注解,对使用不同注解的Mapper使用不同的sqlSessionFactory

第二种配置相对灵活,示例如下:

  1. package bj;
  2.  
  3. import ch.qos.logback.classic.Level;
  4. import ch.qos.logback.classic.Logger;
  5. import com.zaxxer.hikari.HikariDataSource;
  6. import io.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration;
  7. import org.apache.ibatis.annotations.Mapper;
  8. import org.apache.ibatis.annotations.Select;
  9. import org.apache.ibatis.session.SqlSessionFactory;
  10. import org.mybatis.spring.SqlSessionFactoryBean;
  11. import org.mybatis.spring.annotation.MapperScan;
  12. import org.slf4j.LoggerFactory;
  13. import org.springframework.boot.SpringApplication;
  14. import org.springframework.boot.WebApplicationType;
  15. import org.springframework.boot.autoconfigure.SpringBootApplication;
  16. import org.springframework.boot.context.event.ApplicationReadyEvent;
  17. import org.springframework.context.ApplicationListener;
  18. import org.springframework.context.annotation.Bean;
  19. import org.springframework.context.annotation.Configuration;
  20. import org.springframework.context.annotation.Primary;
  21. import org.springframework.jdbc.core.JdbcTemplate;
  22.  
  23. import javax.annotation.Resource;
  24. import javax.sql.DataSource;
  25. import java.lang.annotation.ElementType;
  26. import java.lang.annotation.Retention;
  27. import java.lang.annotation.RetentionPolicy;
  28. import java.lang.annotation.Target;
  29. import java.util.List;
  30. import java.util.Map;
  31.  
  32. /**
  33. * Created by BaiJiFeiLong@gmail.com at 2018/12/6 下午9:29
  34. * <p>
  35. * MyBatis多数据源演示
  36. */
  37. @SpringBootApplication(exclude = {SpringBootConfiguration.class})
  38. @Configuration
  39. @MapperScan(annotationClass = Mapper.class, basePackageClasses = MyBatisApp.class,
  40. sqlSessionFactoryRef = "sqlSessionFactory")
  41. public class MyBatisApp implements ApplicationListener<ApplicationReadyEvent> {
  42.  
  43. /**
  44. * SecondaryMapper配置
  45. * \@MapperScan 注解一次只能添加一个,所以需要单独再加一个配置类
  46. * 自定义@MapperScan会替换MyBatis自动添加的默认@MapperScan。所以主@MapperScan也必须显式添加
  47. */
  48. @Configuration
  49. @MapperScan(annotationClass = SecondaryMapper.class, basePackageClasses = MyBatisApp.class,
  50. sqlSessionFactoryRef = "sqlSessionFactorySecond")
  51. static class SecondaryMapperConfiguration {
  52. }
  53.  
  54. public static void main(String[] args) {
  55. new SpringApplication(MyBatisApp.class) {{
  56. setWebApplicationType(WebApplicationType.NONE);
  57. }}.run(args);
  58. }
  59.  
  60. @Resource
  61. private DataSource dataSource;
  62.  
  63. @Resource
  64. private DataSource dataSourceSecond;
  65.  
  66. @Resource
  67. private JdbcTemplate jdbcTemplate;
  68.  
  69. @Resource
  70. private UserMapper userMapper;
  71.  
  72. @Resource
  73. private SecondaryUserMapper secondaryUserMapper;
  74.  
  75. private void initLogger() {
  76. ((Logger) LoggerFactory.getLogger(MyBatisApp.class)).setLevel(Level.DEBUG);
  77. ((Logger) LoggerFactory.getLogger(JdbcTemplate.class)).setLevel(Level.DEBUG);
  78. }
  79.  
  80. private void initDatabase() {
  81. String oldDatabase = jdbcTemplate.queryForObject("SELECT DATABASE()", String.class);
  82. jdbcTemplate.execute("DROP SCHEMA IF EXISTS one");
  83. jdbcTemplate.execute("CREATE SCHEMA one");
  84. jdbcTemplate.execute("USE one");
  85. jdbcTemplate.execute("CREATE TABLE user(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(32) CHARSET 'utf8')");
  86. jdbcTemplate.execute("INSERT INTO user(name) VALUES ('人民的儿子')");
  87. jdbcTemplate.execute("INSERT INTO user(name) VALUES ('人民的孙子')");
  88. jdbcTemplate.execute("INSERT INTO user(name) VALUES ('人民的曾孙子')");
  89. jdbcTemplate.execute("DROP SCHEMA IF EXISTS two");
  90. jdbcTemplate.execute("CREATE SCHEMA two");
  91. jdbcTemplate.execute("USE two");
  92. jdbcTemplate.execute("CREATE TABLE user(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(32) CHARSET 'utf8')");
  93. jdbcTemplate.execute("INSERT INTO user(name) VALUES ('人民的爹')");
  94. jdbcTemplate.execute("INSERT INTO user(name) VALUES ('人民的爷')");
  95. jdbcTemplate.execute("INSERT INTO user(name) VALUES ('人民的太爷')");
  96. jdbcTemplate.execute("INSERT INTO user(name) VALUES ('人民的老太爷')");
  97. jdbcTemplate.execute("USE " + oldDatabase);
  98. }
  99.  
  100. @Override
  101. public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
  102. initLogger();
  103. initDatabase();
  104. System.out.println("Users:");
  105. userMapper.selectAll().forEach(System.out::println);
  106. System.out.println("Secondary users:");
  107. secondaryUserMapper.selectAll().forEach(System.out::println);
  108. }
  109.  
  110. /**
  111. * 主数据源
  112. * <p>
  113. * 如果不添加@Primary注解, MyBatis可以工作,但是JdbcTemplate无法注入
  114. *
  115. * @return .
  116. */
  117. @Primary
  118. @Bean
  119. public DataSource dataSource() {
  120. return new HikariDataSource() {{
  121. setJdbcUrl("jdbc:mysql://localhost/one?useUnicode=true&characterEncoding=utf8");
  122. setUsername("root");
  123. setPassword("root");
  124. }};
  125. }
  126.  
  127. /**
  128. * 副数据源
  129. *
  130. * @return .
  131. */
  132. @Bean
  133. public DataSource dataSourceSecond() {
  134. return new HikariDataSource() {{
  135. setJdbcUrl("jdbc:mysql://localhost/two?useUnicode=true&characterEncoding=utf8");
  136. setUsername("root");
  137. setPassword("root");
  138. }};
  139. }
  140.  
  141. /**
  142. * 主SqlSessionFactory。使用主数据源。自定义SqlSessionFactory后,MyBatis就不自动添加SqlSessionFactory了,所以必须有
  143. *
  144. * @return .
  145. * @throws Exception .
  146. */
  147. @Bean
  148. public SqlSessionFactory sqlSessionFactory() throws Exception {
  149. return new SqlSessionFactoryBean() {{
  150. setDataSource(dataSource);
  151. }}.getObject();
  152. }
  153.  
  154. /**
  155. * 副SqlSessionFactory。使用副数据源
  156. *
  157. * @return .
  158. * @throws Exception .
  159. */
  160. @Bean
  161. public SqlSessionFactory sqlSessionFactorySecond() throws Exception {
  162. return new SqlSessionFactoryBean() {{
  163. setDataSource(dataSourceSecond);
  164. }}.getObject();
  165. }
  166.  
  167. @Mapper
  168. interface UserMapper {
  169. @Select("SELECT * FROM user")
  170. List<Map<String, Object>> selectAll();
  171. }
  172.  
  173. @SecondaryMapper
  174. interface SecondaryUserMapper {
  175. @Select("SELECT * FROM user")
  176. List<Map<String, Object>> selectAll();
  177. }
  178.  
  179. /**
  180. * 自定义Mapper注解,用于标识使用的数据源
  181. */
  182. @Target(ElementType.TYPE)
  183. @Retention(RetentionPolicy.RUNTIME)
  184. @interface SecondaryMapper {
  185. }
  186. }

控制台输出:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.0.RELEASE)

2018-12-07 11:49:02.596  INFO 5154 --- [           main] bj.MyBatisApp                            : Starting MyBatisApp on MacBook-Air-2.local with PID 5154 (/Users/yuchao/temp/java/hellomaven/target/classes started by yuchao in /Users/yuchao/temp/java/hellomaven)
2018-12-07 11:49:02.633  INFO 5154 --- [           main] bj.MyBatisApp                            : No active profile set, falling back to default profiles: default
2018-12-07 11:49:05.341  INFO 5154 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2018-12-07 11:49:05.499  INFO 5154 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2018-12-07 11:49:05.547  INFO 5154 --- [           main] org.quartz.impl.StdSchedulerFactory      : Using default implementation for ThreadExecutor
2018-12-07 11:49:05.569  INFO 5154 --- [           main] org.quartz.core.SchedulerSignalerImpl    : Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2018-12-07 11:49:05.569  INFO 5154 --- [           main] org.quartz.core.QuartzScheduler          : Quartz Scheduler v.2.3.0 created.
2018-12-07 11:49:05.570  INFO 5154 --- [           main] org.quartz.simpl.RAMJobStore             : RAMJobStore initialized.
2018-12-07 11:49:05.571  INFO 5154 --- [           main] org.quartz.core.QuartzScheduler          : Scheduler meta-data: Quartz Scheduler (v2.3.0) 'quartzScheduler' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

2018-12-07 11:49:05.571  INFO 5154 --- [           main] org.quartz.impl.StdSchedulerFactory      : Quartz scheduler 'quartzScheduler' initialized from an externally provided properties instance.
2018-12-07 11:49:05.571  INFO 5154 --- [           main] org.quartz.impl.StdSchedulerFactory      : Quartz scheduler version: 2.3.0
2018-12-07 11:49:05.571  INFO 5154 --- [           main] org.quartz.core.QuartzScheduler          : JobFactory set to: org.springframework.scheduling.quartz.SpringBeanJobFactory@769a58e5
2018-12-07 11:49:05.780  WARN 5154 --- [           main] reactor.netty.tcp.TcpResources           : [http] resources will use the default LoopResources: DefaultLoopResources {prefix=reactor-http, daemon=true, selectCount=4, workerCount=4}
2018-12-07 11:49:05.780  WARN 5154 --- [           main] reactor.netty.tcp.TcpResources           : [http] resources will use the default ConnectionProvider: PooledConnectionProvider {name=http, poolFactory=reactor.netty.resources.ConnectionProvider$$Lambda$284/1788545647@10667848}
2018-12-07 11:49:06.061  INFO 5154 --- [           main] o.s.s.quartz.SchedulerFactoryBean        : Starting Quartz Scheduler now
2018-12-07 11:49:06.062  INFO 5154 --- [           main] org.quartz.core.QuartzScheduler          : Scheduler quartzScheduler_$_NON_CLUSTERED started.
2018-12-07 11:49:06.079  INFO 5154 --- [           main] bj.MyBatisApp                            : Started MyBatisApp in 4.645 seconds (JVM running for 6.354)
2018-12-07 11:49:06.084 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL query [SELECT DATABASE()]
2018-12-07 11:49:06.105 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [DROP SCHEMA IF EXISTS one]
2018-12-07 11:49:06.115 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [CREATE SCHEMA one]
2018-12-07 11:49:06.117 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [USE one]
2018-12-07 11:49:06.119 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [CREATE TABLE user(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(32) CHARSET 'utf8')]
2018-12-07 11:49:06.153 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [INSERT INTO user(name) VALUES ('人民的儿子')]
2018-12-07 11:49:06.157 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [INSERT INTO user(name) VALUES ('人民的孙子')]
2018-12-07 11:49:06.161 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [INSERT INTO user(name) VALUES ('人民的曾孙子')]
2018-12-07 11:49:06.164 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [DROP SCHEMA IF EXISTS two]
2018-12-07 11:49:06.174 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [CREATE SCHEMA two]
2018-12-07 11:49:06.176 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [USE two]
2018-12-07 11:49:06.178 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [CREATE TABLE user(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(32) CHARSET 'utf8')]
2018-12-07 11:49:06.226 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [INSERT INTO user(name) VALUES ('人民的爹')]
2018-12-07 11:49:06.231 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [INSERT INTO user(name) VALUES ('人民的爷')]
2018-12-07 11:49:06.235 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [INSERT INTO user(name) VALUES ('人民的太爷')]
2018-12-07 11:49:06.243 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [INSERT INTO user(name) VALUES ('人民的老太爷')]
2018-12-07 11:49:06.246 DEBUG 5154 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [USE one]
Users:
2018-12-07 11:49:06.271 DEBUG 5154 --- [           main] bj.MyBatisApp$UserMapper.selectAll       : ==>  Preparing: SELECT * FROM user
2018-12-07 11:49:06.297 DEBUG 5154 --- [           main] bj.MyBatisApp$UserMapper.selectAll       : ==> Parameters:
2018-12-07 11:49:06.314 DEBUG 5154 --- [           main] bj.MyBatisApp$UserMapper.selectAll       : <==      Total: 3
{name=人民的儿子, id=1}
{name=人民的孙子, id=2}
{name=人民的曾孙子, id=3}
Secondary users:
2018-12-07 11:49:06.318  INFO 5154 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Starting...
2018-12-07 11:49:06.324  INFO 5154 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Start completed.
2018-12-07 11:49:06.325 DEBUG 5154 --- [           main] b.M.selectAll                            : ==>  Preparing: SELECT * FROM user
2018-12-07 11:49:06.325 DEBUG 5154 --- [           main] b.M.selectAll                            : ==> Parameters:
2018-12-07 11:49:06.328 DEBUG 5154 --- [           main] b.M.selectAll                            : <==      Total: 4
{name=人民的爹, id=1}
{name=人民的爷, id=2}
{name=人民的太爷, id=3}
{name=人民的老太爷, id=4}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对w3xue的支持。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号