, Spring Boot will look for jar packages of in-memory databases such as H2, HSQL, Derby, etc. in the classpath to automatically configure a DataSource of an in-memory database.
<dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <scope>runtime</scope> </dependency>
However, if spring.datasource.* related information is set in application.properties, Spring Boot will use this setting to automatically configure the DataSource.
quote
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
(2) Multiple data sources
Data sources are not limited to databases:
- Various databases, such as: DB1 in MySQL, DB2 in PostgreSQL, DB3 in Oracle
- Multiple libraries in a database, such as DB1, DB2, DB3 in MySQL
quote
# MySQL database
spring.ds_mysql.url=jdbc:mysql://localhost:3306/rensanning
spring.ds_mysql.username=root
spring.ds_mysql.password=root
spring.ds_mysql.driverClassName=com.mysql.jdbc.Driver
# PostgreSQL database
spring.ds_pg.url=jdbc:postgresql://localhost:5432/rensanning
spring.ds_pg.username=postgres
spring.ds_pg.password=postgres
spring.ds_pg.driverClassName=org.postgresql.Driver
# Oracle database
spring.ds_oracle.url=jdbc:oracle:thin:@localhost:1521:rensanning
spring.ds_oracle.username=scott
spring.ds_oracle.password=tiger
spring.ds_oracle.driverClassName=oracle.jdbc.driver.OracleDriver
spring.ds_mysql.url=jdbc:mysql://localhost:3306/rensanning
spring.ds_mysql.username=root
spring.ds_mysql.password=root
spring.ds_mysql.driverClassName=com.mysql.jdbc.Driver
# PostgreSQL database
spring.ds_pg.url=jdbc:postgresql://localhost:5432/rensanning
spring.ds_pg.username=postgres
spring.ds_pg.password=postgres
spring.ds_pg.driverClassName=org.postgresql.Driver
# Oracle database
spring.ds_oracle.url=jdbc:oracle:thin:@localhost:1521:rensanning
spring.ds_oracle.username=scott
spring.ds_oracle.password=tiger
spring.ds_oracle.driverClassName=oracle.jdbc.driver.OracleDriver
@Configuration public class MultipleDBConfig { @Bean(name = "mysqlDB") @Primary @ConfigurationProperties(prefix = "spring.ds_mysql") public DataSource mysqlDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "postgresDB") @ConfigurationProperties(prefix = "spring.ds_pg") public DataSource postgresDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "oracleDB") @ConfigurationProperties(prefix = "ds_oracle") public DataSource oracleDataSource() { return DataSourceBuilder.create().build(); } }
Beans marked as @Primary are used first when using @Autowired injection.
@Autowired private DataSource mysqlDataSource; @Autowired @Qualifier("postgresDB") private DataSource postgresDataSource; @Autowired @Qualifier("oracleDB") private DataSource oracleDataSource;
(3) Dynamic data source
Spring provides org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource to support DataSource routing configuration. For details, please refer to the official website Blog: https://spring.io/blog/2007/01/23/dynamic-datasource -routing/
a - define configuration
public enum SchemaType { DEFAULT, MASTER, SLAVE }
@Component @Configuration public class DatasourceConfig { public DataSource defaultDatasource(){ DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/rensanning01"); ds.setUsername("user01"); ds.setPassword("pass01"); return ds; } public DataSource masterDatasource(){ DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/rensanning02"); ds.setUsername("user02"); ds.setPassword("pass02"); return ds; } public DataSource slaveDatasource(){ DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/rensanning03"); ds.setUsername("user03"); ds.setPassword("pass03"); return ds; } @Bean public DynamicRoutingDataSourceResolver dataSource() { DynamicRoutingDataSourceResolver resolver = new DynamicRoutingDataSourceResolver(); Map<Object, Object> dataSources = new HashMap<Object,Object>(); dataSources.put("default", defaultDatasource()); dataSources.put("master", masterDatasource()); dataSources.put("slave", slaveDatasource()); resolver.setTargetDataSources(dataSources); // default datasource resolver.setDefaultTargetDataSource(masterDatasource()); return resolver; } }
public class DynamicRoutingDataSourceResolver extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { if (SchemaContextHolder.getSchemaType() == null) { return "default"; } if(SchemaContextHolder.getSchemaType() == SchemaType.MASTER) { return "master"; } if(SchemaContextHolder.getSchemaType() == SchemaType.SLAVE) { return "slave"; } return "default"; } }
public class SchemaContextHolder { private static ThreadLocal<SchemaType> contextHolder = new ThreadLocal<SchemaType>(); public static void setSchemaType(SchemaType datasourcename) { contextHolder.set(datasourcename); } public static SchemaType getSchemaType() { return contextHolder.get(); } public static void clear() { contextHolder.remove(); } }
b - When switching data
sources, SchemaContextHolder.setSchemaType(SchemaType.MASTER) is required to switch data sources; call clear() after completion. for example:
@GetMapping("findall") public List<User> findall(@RequestParam("ds") String ds) { if(ds.equals("master")) { SchemaContextHolder.setSchemaType(SchemaType.MASTER); } else { SchemaContextHolder.setSchemaType(SchemaType.SLAVE); } return userService.findAll(); }
Switch data sources through Interceptor.
public class DatasourceInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if(!StringUtils.isEmpty(request.getSession().getAttribute("datasource"))){ SchemaContextHolder.setSchemaType((SchemaType)request.getSession().getAttribute("datasource")); } return true; } }
@Component @Configuration public class DatasourceConfig { // ... @Bean public HandlerInterceptor datasourceInterceptor(){ return new DatasourceInterceptor(); } @Bean public MappedInterceptor interceptorMapping(){ return new MappedInterceptor(new String[]{"/**"}, datasourceInterceptor()); } // ... }
The database can be switched by modifying the value in the Session: request.getSession().setAttribute("datasource", type); (4) Multiple Datasources can already be obtained from the
specified datasource based on the package
, then they can be generated by DataSource For different SqlSessionFactoryBeans, specify different SqlSessionFactoryBeans for different packages through @MapperScan.
https://github.com/mybatis/spring-boot-starter/issues/78
@MapperScan(basePackages = "com.rensanning.springboot.mappers.cmn", sqlSessionFactoryRef = CmnDatasourceConfig.SQL_SESSION_FACTORY_NAME) @MapperScan(basePackages = "com.rensanning.springboot.mappers.user", sqlSessionFactoryRef = UsrDatasourceConfig.SQL_SESSION_FACTORY_NAME)
(5) Managing data sources through the database The
above scenario is basically that all database information is known, and can be fixed in the code (or application.properties)! Another very common scenario is that a user logs in using a data source, but The logged-in data source needs to be obtained from the DB, and the DataSource route needs to be updated in real time. You can manage operations such as creating and acquiring data sources by yourself by implementing AbstractDataSource.
Specific reference to the attachment code: Click to download
the reference:
http://qiita.com/syukai/items/0d4bf27f82fef9965cdd
http://qiita.com/kazuki43zoo/items/9d8aec0ecab117a4d5c1