您的位置:首页 > 编程语言 > Java开发

历史上最详细的SpringBoot多数据源配置及使用流程

2017-07-21 19:15 295 查看
关于标题—>只是想看看标题党的效果如何

一、场景(简化)

要实现一个用户数据中心的系统架构,其中要用到两个数据库,一个database名为sso,主要存放用户的信息。另一个database名为configuration,存放一些配置信息。当A系统通过接口过来请求用户信息时,需要在配置库查询A系统的权限,然后将对应权限的用户信息返回给A系统。所以就需要使用两个不同的库,要在同一个项目中配置两套EntityManager(或者Hibernate的session)和事物管理。

连接池使用阿里巴巴的Druid,持久框架使用的Hibernate,需要引入
spring-boot-starter-data-jpa


二、实体的包结构

com.kingboy.configuration.domain(配置中心的实体)

com.kingboy.ssoservice.domain(用户信息的实体)

三、配置文件(application.properties)

分别编写两套数据源的配置,我主要用不同的模块名称来区分不同的数据源。

spring.datasource.configuration.*

spring.datasource.sso.*

#-----------------------------------通用数据源配置-----------------------------
spring.jpa.hibernate.ddl-auto=update
spring.jpa.open-in-view=false
spring.jpa.show-sql=true
#---------------------------------------------------------
#configuration数据源
spring.datasource.configuration.url=jdbc:mysql://localhost:3306/configration?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.configuration.username=root
spring.datasource.configuration.password=123456
spring.datasource.configuration.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.configuration.maxActive=20
spring.datasource.configuration.initialSize=5
spring.datasource.configuration.minIdle=5
spring.datasource.configuration.maxWait=60000
spring.datasource.configuration.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.configuration.timeBetweenEvictionRunsMillis=60000
spring.datasource.configuration.minEvictableIdleTimeMillis=300000
spring.datasource.configuration.poolPreparedStatements=true
#---------------------------------------------------------
#sso数据源
spring.datasource.sso.url=jdbc:mysql://localhost:3306/sso?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.sso.username=root
spring.datasource.sso.password=123456
spring.datasource.sso.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.sso.maxActive=20
spring.datasource.sso.initialSize=5
spring.datasource.sso.minIdle=5
spring.datasource.sso.maxWait=60000
spring.datasource.sso.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.sso.timeBetweenEvictionRunsMillis=60000
spring.datasource.sso.minEvictableIdleTimeMillis=300000
spring.datasource.sso.poolPreparedStatements=true


这么多属性一看就很萌逼了,我们先把它加载到一个信息载体类中,方便以后使用。

configuration数据源的信息载体类:

package com.kingboy.configuration.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
* @Author kingboy
* @Date 2017/6/19 下午5:15
* @Description ConfigurationProperties is used to configuration的数据池属性
*/
@ConfigurationProperties(prefix = "spring.datasource.configuration")
@Component
public class ConfigurationDataSourceProperties {

public String url;

public String username;

public String password;

public String driverClassName;

public Integer maxActive;

public Integer initialSize;

public Integer minIdle;

public Integer maxWait;

public Integer maxPoolPreparedStatementPerConnectionSize;

public Integer timeBetweenEvictionRunsMillis;

public Integer minEvictableIdleTimeMillis;

public Boolean poolPreparedStatements;

}


sso数据源的信息载体类:

package com.kingboy.ssoservice.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
* @Author kingboy
* @Date 2017/6/19 下午5:15
* @Description ConfigurationProperties is used to configuration的数据池属性
*/
@ConfigurationProperties(prefix = "spring.datasource.sso")
@Component
public class SSODataSourceProperties {

public String url;

public String username;

public String password;

public String driverClassName;

public Integer maxActive;

public Integer initialSize;

public Integer minIdle;

public Integer maxWait;

public Integer maxPoolPreparedStatementPerConnectionSize;

public Integer timeBetweenEvictionRunsMillis;

public Integer minEvictableIdleTimeMillis;

public Boolean poolPreparedStatements;

}


四、配置configuration和sso的实体管理Bean和事物管理Bean

具体的配置说明都写在代码注释里面了。

configuration的配置

package com.kingboy.configuration.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.util.Map;

/**
* @Author kingboy
* @Date 2017/6/18 下午11:13
* @Description ConfigurationDataSource is used to 数据源配置
*/
@Configuration
@EnableTransactionManagement//开启事物管理
@EnableJpaRepositories(//自定义数据管理的配置
//指定EntityManager的创建工厂Bean
entityManagerFactoryRef="configurationEntityManagerFactory",
//指定事物管理的Bean
transactionManagerRef="configurationTransactionManager",
//指定管理的实体位置
basePackages= {"com.kingboy.configuration.domain"})
public class ConfigurationJPAConfig {

/*
* 配置数据源
*/
@Bean
public DataSource configurationDataSource() {
DruidDataSource dataSource = new DruidDataSource();
//设置数据源的属性
setDruidProperties(dataSource);
return dataSource;
}

@Autowired
ConfigurationDataSourceProperties config;//注入数据源配置信息

//设置数据源的属性的方法
private void setDruidProperties(DruidDataSource dataSource) {
dataSource.setUrl(config.url);
dataSource.setUsername(config.username);
dataSource.setPassword(config.password);
dataSource.setDriverClassName(config.driverClassName);
dataSource.setMaxActive(config.maxActive);
dataSource.setInitialSize(config.initialSize);
dataSource.setMinIdle(config.minIdle);
dataSource.setMaxWait(config.maxWait);
dataSource.setMaxPoolPreparedStatementPerConnectionSize(config.maxPoolPreparedStatementPerConnectionSize);
dataSource.setTimeBetweenEvictionRunsMillis(config.timeBetweenEvictionRunsMillis);
dataSource.setMinEvictableIdleTimeMillis(config.minEvictableIdleTimeMillis);
dataSource.setPoolPreparedStatements(config.poolPreparedStatements);
}

/*
* 配置实体管理工厂Bean
*/
@Bean
public LocalContainerEntityManagerFactoryBean configurationEntityManagerFactory (EntityManagerFactoryBuilder builder) {
return builder
.dataSource(configurationDataSource())
.packages("com.kingboy.configuration.domain")//设置实体类所在位置
.persistenceUnit("configuration")
.properties(getProperties(configurationDataSource()))//设置hibernate通用配置
.build();
}

@Autowired
private JpaProperties jpaProperties;//注入spring自带的jpa属性类

/*
*拿到hibernate的通用配置
*/
private Map<String, String> getProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
}

/*
*配置事物管理的Bean
*/
@Bean
public PlatformTransactionManager configurationTransactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(configurationEntityManagerFactory(builder).getObject());
}

}


sso的配置

package com.kingboy.ssoservice.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.Map;

/**
* @Author kingboy
* @Date 2017/6/18 下午11:13
* @Description ConfigurationDataSource is used to 数据源配置
*/
@Configuration
@EnableTransactionManagement//开启事物管理
@EnableJpaRepositories(//自定义数据管理的配置
//指定EntityManager的创建工厂Bean
entityManagerFactoryRef="ssoEntityManagerFactory",
//指定事物管理的Bean
transactionManagerRef="ssoTransactionManager",
//指定管理的实体位置
basePackages= {"com.kingboy.ssoservice.domain"}) //设置Repository所在位置
public class SSOJPAConfig {

/*
* 配置数据源
*/
@Bean
@Primary//主数据源,或者叫默认数据源,下面的@Primary同理
public DataSource ssoDataSource() {
DruidDataSource dataSource = new DruidDataSource();
setDruidProperties(dataSource);
return dataSource;
}

//注入数据源配置信息
@Autowired
SSODataSourceProperties config;

private void setDruidProperties(DruidDataSource dataSource) {
dataSource.setUrl(config.url);
dataSource.setUsername(config.username);
dataSource.setPassword(config.password);
dataSource.setDriverClassName(config.driverClassName);
dataSource.setMaxActive(config.maxActive);
dataSource.setInitialSize(config.initialSize);
dataSource.setMinIdle(config.minIdle);
dataSource.setMaxWait(config.maxWait);
dataSource.setMaxPoolPreparedStatementPerConnectionSize(config.maxPoolPreparedStatementPerConnectionSize);
dataSource.setTimeBetweenEvictionRunsMillis(config.timeBetweenEvictionRunsMillis);
dataSource.setMinEvictableIdleTimeMillis(config.minEvictableIdleTimeMillis);
dataSource.setPoolPreparedStatements(config.poolPreparedStatements);
}

/*
* 配置实体管理工厂Bean
*/
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean ssoEntityManagerFactory (EntityManagerFactoryBuilder builder) {
return builder
.dataSource(ssoDataSource())
.packages("com.kingboy.ssoservice.domain") //设置实体类所在位置
.persistenceUnit("sso")
.properties(getProperties(ssoDataSource()))//设置hibernate通用配置
.build();
}

@Autowired
private JpaProperties jpaProperties;//注入spring自带的jpa属性类

/*
*拿到hibernate的通用配置
*/
private Map<String, String> getProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
}

/*
*配置事物管理的Bean
*/
@Bean
public PlatformTransactionManager ssoTransactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(ssoEntityManagerFactory(builder).getObject());
}

}


五、关于第四节的说明

@Bean注解如果没有指定bean的名字,那么会以方法名作为bean的名字。所以就有了@EnableJpaRepositories注解中的
entityManagerFactoryRef="ssoEntityManagerFactory"
transactionManagerRef="ssoTransactionManager"


private JpaProperties jpaProperties;
是spring自动注入的,可以获取到配置文件中『通用数据源配置』的信息,如show-sql等属性。

只所以将sso与configuration分开配置,一是为了整洁。二是为了模块解耦,如果是多模块项目,会很好拆分。

六、使用

为了方便阅读,随便写个栗子,就从controller开始写了。也不使用接口编程了,这样看起来更顺畅。

实体类(注解就不加了)

public class User {
private Integer id;
private String telephone;
private String password;
//setter getter
}

public class Configuration {
private Integer id;
private String formatId;
private String secret;
//setter getter
}


Controller

@RestController
@RequestMapping(produces = "application/json")
public class UserController {

@Resource
UserService userService;

@Resource
ConfigurationService configurationService;

/**
* 添加User
* @return
*/
//为了方便用了restfule的形式,正常要用post,https
@GetMapping(value = "/AddUser/{telephone}/{password}")
public ApiResult add(@PathVariable String telephone, @PathVariable String password) {
userService.addUser(telephone, password);
return ApiResult.success("add user success!");
}

/**
* 添加配置
* @return
*/
//为了方便用了restfule的形式,正常要用post,https
@GetMapping(value = "/AddConfig/{formatId}/{secret}")
public ApiResult add(@PathVariable String formatId, @PathVariable String secret) {
configurationService.addConfig(formatId, secret);
return ApiResult.success("add config success!");
}

}


Service

@Service
public class UserServiceImpl{

@Resource
UserRepository userRepository;

@Override
@Transactional(rollbackFor = Exception.class, value = "ssoTransactionManager")//对应的事物管理Bean的名字
public void addUser(String telephone,String password) {
userRepository.addUser(telephone, password);
}

}

@Service
public class ConfigurationServiceImpl{

@Resource
ConfigurationRepository configurationRepository;

@Override
@Transactional(rollbackFor = Exception.class, value = "configurationTransactionManager")//对应的事物管理Bean的名字
public void addConfig(String formatId,String secret) {
configurationRepository.addConfig(formatId, secret);
}

}


Repository

@Repository
public class UserRepositoryImpl {

@Autowired
@Qualifier("ssoEntityManagerFactory")//实体管理工厂Bean的名字
EntityManager ssoEntityManager;

@Override
public void addUser(String telephone, String password) {
User user = new User(null, telephone, password);
ssoEntityManager.persist(user);
}

}

@Repository
public class ConfigurationRepositoryImpl {

@Autowired
@Qualifier("configurationEntityManagerFactory")//实体管理工厂Bean的名字
EntityManager configurationEntityManager;

@Override
public void addConfig(String formatId, String secret) {
Configuration config = new Configuration(null, formatId, secret);
configurationEntityManager.persist(config);
}

}


上面代码手写,可能个别地方会有个小纰漏。

至此,全部搞定……m……m……p
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  多数据源 springboot