MyBatis多資料來源的配置
MyBatis多資料來源的配置主要有兩種方式:
- 通過@MapperScan註解,對不同包下的Mapper使用不同的sqlSessionFactory
- 通過@MapperScan註解加自定義註解,對使用不同註解的Mapper使用不同的sqlSessionFactory
第二種配置相對靈活,示例如下:
package bj; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import com.zaxxer.hikari.HikariDataSource; import io.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.jdbc.core.JdbcTemplate; import javax.annotation.Resource; import javax.sql.DataSource; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.List; import java.util.Map; /** * Created by [email protected] at 2018/12/6 下午9:29 * <p> * MyBatis多資料來源演示 */ @SpringBootApplication(exclude = {SpringBootConfiguration.class}) @Configuration @MapperScan(annotationClass = Mapper.class, basePackageClasses = MyBatisApp.class, sqlSessionFactoryRef = "sqlSessionFactory") public class MyBatisApp implements ApplicationListener<ApplicationReadyEvent> { /** * SecondaryMapper配置 * \@MapperScan 註解一次只能新增一個,所以需要單獨再加一個配置類 * 自定義@MapperScan會替換MyBatis自動新增的預設@MapperScan。所以主@MapperScan也必須顯式新增 */ @Configuration @MapperScan(annotationClass = SecondaryMapper.class, basePackageClasses = MyBatisApp.class, sqlSessionFactoryRef = "sqlSessionFactorySecond") static class SecondaryMapperConfiguration { } public static void main(String[] args) { new SpringApplication(MyBatisApp.class) {{ setWebApplicationType(WebApplicationType.NONE); }}.run(args); } @Resource private DataSource dataSource; @Resource private DataSource dataSourceSecond; @Resource private JdbcTemplate jdbcTemplate; @Resource private UserMapper userMapper; @Resource private SecondaryUserMapper secondaryUserMapper; private void initLogger() { ((Logger) LoggerFactory.getLogger(MyBatisApp.class)).setLevel(Level.DEBUG); ((Logger) LoggerFactory.getLogger(JdbcTemplate.class)).setLevel(Level.DEBUG); } private void initDatabase() { String oldDatabase = jdbcTemplate.queryForObject("SELECT DATABASE()", String.class); jdbcTemplate.execute("DROP SCHEMA IF EXISTS one"); jdbcTemplate.execute("CREATE SCHEMA one"); jdbcTemplate.execute("USE one"); jdbcTemplate.execute("CREATE TABLE user(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(32) CHARSET 'utf8')"); jdbcTemplate.execute("INSERT INTO user(name) VALUES ('人民的兒子')"); jdbcTemplate.execute("INSERT INTO user(name) VALUES ('人民的孫子')"); jdbcTemplate.execute("INSERT INTO user(name) VALUES ('人民的曾孫子')"); jdbcTemplate.execute("DROP SCHEMA IF EXISTS two"); jdbcTemplate.execute("CREATE SCHEMA two"); jdbcTemplate.execute("USE two"); jdbcTemplate.execute("CREATE TABLE user(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(32) CHARSET 'utf8')"); jdbcTemplate.execute("INSERT INTO user(name) VALUES ('人民的爹')"); jdbcTemplate.execute("INSERT INTO user(name) VALUES ('人民的爺')"); jdbcTemplate.execute("INSERT INTO user(name) VALUES ('人民的太爺')"); jdbcTemplate.execute("INSERT INTO user(name) VALUES ('人民的老太爺')"); jdbcTemplate.execute("USE " + oldDatabase); } @Override public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { initLogger(); initDatabase(); System.out.println("Users:"); userMapper.selectAll().forEach(System.out::println); System.out.println("Secondary users:"); secondaryUserMapper.selectAll().forEach(System.out::println); } /** * 主資料來源 * <p> * 如果不新增@Primary註解, MyBatis可以工作,但是JdbcTemplate無法注入 * * @return . */ @Primary @Bean public DataSource dataSource() { return new HikariDataSource() {{ setJdbcUrl("jdbc:mysql://localhost/one?useUnicode=true&characterEncoding=utf8"); setUsername("root"); setPassword("root"); }}; } /** * 副資料來源 * * @return . */ @Bean public DataSource dataSourceSecond() { return new HikariDataSource() {{ setJdbcUrl("jdbc:mysql://localhost/two?useUnicode=true&characterEncoding=utf8"); setUsername("root"); setPassword("root"); }}; } /** * 主SqlSessionFactory。使用主資料來源。自定義SqlSessionFactory後,MyBatis就不自動新增SqlSessionFactory了,所以必須有 * * @return . * @throws Exception . */ @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { return new SqlSessionFactoryBean() {{ setDataSource(dataSource); }}.getObject(); } /** * 副SqlSessionFactory。使用副資料來源 * * @return . * @throws Exception . */ @Bean public SqlSessionFactory sqlSessionFactorySecond() throws Exception { return new SqlSessionFactoryBean() {{ setDataSource(dataSourceSecond); }}.getObject(); } @Mapper interface UserMapper { @Select("SELECT * FROM user") List<Map<String, Object>> selectAll(); } @SecondaryMapper interface SecondaryUserMapper { @Select("SELECT * FROM user") List<Map<String, Object>> selectAll(); } /** * 自定義Mapper註解,用於標識使用的資料來源 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface SecondaryMapper { } }
控制檯輸出:
._______ _ _ /\\ / ___'_ __ _ _(_)_ ____ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/___)| |_)| | | | | || (_| |) ) ) ) '|____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot ::(v2.1.0.RELEASE) 2018-12-07 11:49:02.596INFO 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.633INFO 5154 --- [main] bj.MyBatisApp: No active profile set, falling back to default profiles: default 2018-12-07 11:49:05.341INFO 5154 --- [main] com.zaxxer.hikari.HikariDataSource: HikariPool-1 - Starting... 2018-12-07 11:49:05.499INFO 5154 --- [main] com.zaxxer.hikari.HikariDataSource: HikariPool-1 - Start completed. 2018-12-07 11:49:05.547INFO 5154 --- [main] org.quartz.impl.StdSchedulerFactory: Using default implementation for ThreadExecutor 2018-12-07 11:49:05.569INFO 5154 --- [main] org.quartz.core.SchedulerSignalerImpl: Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl 2018-12-07 11:49:05.569INFO 5154 --- [main] org.quartz.core.QuartzScheduler: Quartz Scheduler v.2.3.0 created. 2018-12-07 11:49:05.570INFO 5154 --- [main] org.quartz.simpl.RAMJobStore: RAMJobStore initialized. 2018-12-07 11:49:05.571INFO 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.571INFO 5154 --- [main] org.quartz.impl.StdSchedulerFactory: Quartz scheduler 'quartzScheduler' initialized from an externally provided properties instance. 2018-12-07 11:49:05.571INFO 5154 --- [main] org.quartz.impl.StdSchedulerFactory: Quartz scheduler version: 2.3.0 2018-12-07 11:49:05.571INFO 5154 --- [main] org.quartz.core.QuartzScheduler: JobFactory set to: org.springframework.scheduling.quartz.SpringBeanJobFactory@769a58e5 2018-12-07 11:49:05.780WARN 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.780WARN 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.061INFO 5154 --- [main] o.s.s.quartz.SchedulerFactoryBean: Starting Quartz Scheduler now 2018-12-07 11:49:06.062INFO 5154 --- [main] org.quartz.core.QuartzScheduler: Scheduler quartzScheduler_$_NON_CLUSTERED started. 2018-12-07 11:49:06.079INFO 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.318INFO 5154 --- [main] com.zaxxer.hikari.HikariDataSource: HikariPool-2 - Starting... 2018-12-07 11:49:06.324INFO 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}
文章首發:ofollow,noindex" target="_blank">https://baijifeilong.github.io