Getting Started with Spring Boot - Basics (11) - Data Source Configuration

(1) By default for a single data source

, 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


(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


@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

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326654774&siteId=291194637