如何使用多数据源,同时使用jpa和jdbctemplate

Posted 必须往前走

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用多数据源,同时使用jpa和jdbctemplate相关的知识,希望对你有一定的参考价值。

技术分享图片
spring:
 datasource:
    first:
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://xx.xx.xx.xx:xx/xx?characterEncoding=utf8
    driver-class-name: com.mysql.jdbc.Driver
    username: xx
    password: xx
    #配置监控统计拦截的filters,去掉监控界面sql将无法统计,wall用于防火墙
    filters: stat,wall,log4j
    #最大活跃数
    maxActive: 20
    #初始化连接数
    initialSize: 1
    #最大连接等待超过时间
    maxWait: 60000
    #打开PSCache,并且指定每个连接PSCache的大小
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    #通过connectionProperties属性来打开mergeSql功能;慢SQL记录
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
    minIdle: 1
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: select 1 from dual
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
  sec:
     type: com.alibaba.druid.pool.DruidDataSource
     url: jdbc:mysql://xx.xx.xx.xx:3306/xx?characterEncoding=utf8
     driver-class-name: com.mysql.jdbc.Driver
     username: xx
     password: xx
     #配置监控统计拦截的filters,去掉监控界面sql将无法统计,wall用于防火墙
     filters: stat,wall,log4j
     #最大活跃数
     maxActive: 20
     #初始化连接数
     initialSize: 1
     #最大连接等待超过时间
     maxWait: 60000
     #打开PSCache,并且指定每个连接PSCache的大小
     poolPreparedStatements: true
     maxPoolPreparedStatementPerConnectionSize: 20
     #通过connectionProperties属性来打开mergeSql功能;慢SQL记录
     connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
     minIdle: 1
     timeBetweenEvictionRunsMillis: 60000
     minEvictableIdleTimeMillis: 300000
     validationQuery: select 1 from dual
     testWhileIdle: true
     testOnBorrow: false
     testOnReturn: false
配置文件

 

技术分享图片
@ServletComponentScan
@Configuration
public class DatasourceConfiguration {

    private Logger logger = LoggerFactory.getLogger(DatasourceConfiguration.class);

    @Value("${spring.datasource.first.url}")
    private String firstdevUrl;
    @Value("${spring.datasource.first.username}")
    private String firstUsername;
    @Value("${spring.datasource.first.password}")
    private String firstPassword;

    @Value("${spring.datasource.sec.url}")
    private String secUrl;
    @Value("${spring.datasource.sec.username}")
    private String secUsername;
    @Value("${spring.datasource.sec.password}")
    private String secPassword;



    @Value("com.mysql.jdbc.Driver")
    private String driverClassName;

    @Value("5")
    private int initialSize;

    @Value("5")
    private int minIdle;

    @Value("20")
    private int maxActive;

    @Value("60000")
    private int maxWait;

    /**
     * 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
     */
    @Value("60000")
    private int timeBetweenEvictionRunsMillis;
    /**
     * 配置一个连接在池中最小生存的时间,单位是毫秒
     */
    @Value("300000")
    private int minEvictableIdleTimeMillis;

    @Value("SELECT 1 FROM DUAL")
    private String validationQuery;

    @Value("true")
    private boolean testWhileIdle;

    @Value("false")
    private boolean testOnBorrow;

    @Value("false")
    private boolean testOnReturn;

    /**
     * 打开PSCache,并且指定每个连接上PSCache的大小
     */
    @Value("true")
    private boolean poolPreparedStatements;

    @Value("20")
    private int maxPoolPreparedStatementPerConnectionSize;
    /**
     * 配置监控统计拦截的filters,去掉后监控界面sql无法统计,‘wall‘用于防火墙
     */
    @Value("stat,wall,log4j")
    private String filters;
    /**
     * 通过connectProperties属性来打开mergeSql功能;慢SQL记录
     */
    @Value("druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500")
    private String connectionProperties;


    @Bean(name = "secDatasource")
    @Qualifier("secDatasource")
    @ConfigurationProperties(prefix = "spring.datasource.sec")
    public DataSource secDataSource() {
        return getDruidDataSource(secUsername, secPassword, secUrl);
    }

    
    @Bean(name = "firstDatasource")
    @Qualifier("firstDatasource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.first")
    public DataSource firstDataSource() {
        return getDruidDataSource(firstUsername, firstPassword, firstUrl);
    }

   

    private DruidDataSource getDruidDataSource(String username, String password, String url) {
        DruidDataSource datasource = new DruidDataSource();

        datasource.setUrl(url);
        datasource.setUsername(username);
        datasource.setPassword(password);
        datasource.setDriverClassName(driverClassName);

        //configuration
        datasource.setInitialSize(initialSize);
        datasource.setMinIdle(minIdle);
        datasource.setMaxActive(maxActive);
        datasource.setMaxWait(maxWait);
        datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        datasource.setValidationQuery(validationQuery);
        datasource.setTestWhileIdle(testWhileIdle);
        datasource.setTestOnBorrow(testOnBorrow);
        datasource.setTestOnReturn(testOnReturn);
        datasource.setPoolPreparedStatements(poolPreparedStatements);
        datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
        try {
            datasource.setFilters(filters);
        } catch (SQLException e) {
            logger.error("druid configuration initialization filter : {0}", e);
        }
        datasource.setConnectionProperties(connectionProperties);
        return datasource;
    }

}
配置数据源
技术分享图片
package com.ipinyou.mip.configuration;

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 com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;


/**
 * 这样的方式不需要添加注解:@ServletComponentScan
 * Created by Administrator on 2018/2/28.
 */
@Configuration
public class DruidConfiguration {

    @Bean
    public ServletRegistrationBean statViewServlet(){
        //创建Servlet,注册实体
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(),"/druid/*");
        //设置ip白名单
        servletRegistrationBean.addInitParameter("allow","xx.xx.xx.xx");
        //设置ip黑名单,如果deny和allow共同存在时,deny优先于allow
        servletRegistrationBean.addInitParameter("deny","xx.xx.xx.xx");
        //设置控制台管理用户
        servletRegistrationBean.addInitParameter("loginUsername","xxx");
        servletRegistrationBean.addInitParameter("loginPassword","xxx");
        //是否可以重置数据
        servletRegistrationBean.addInitParameter("resetEnable","false");
        return servletRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean statFilter(){
        //创建过滤器
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
        //设置过滤器过滤路径
        filterRegistrationBean.addUrlPatterns("/*");
        //忽略过滤形式
        filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
        return filterRegistrationBean;
    }
}
设置数据源的过滤器
技术分享图片
package com.ipinyou.mip.configuration;

import java.util.Map;

import javax.persistence.EntityManager;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
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;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryPrimary",
        transactionManagerRef = "transactionManagerPrimary",
        basePackages = {"xx.xx.xxx","xx.xx.xx"})//设置dao(repo)所在位置
public class JpaConfiguration {

    @Autowired
    @Qualifier("firstDatasource")
    private DataSource firstDataSource;
    
    @Primary
    @Bean(name = "entityManagerFirst")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
    }

    @Autowired
    private JpaProperties jpaProperties;

    private Map<String, Object> getVendorProperties() {
        return jpaProperties.getHibernateProperties(new HibernateSettings());
    }

    /**
     * 设置实体类所在位置
     */
    @Primary
    @Bean(name = "entityManagerFactoryPrimary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(mipdevDataSource)
                .packages("xx.xx.xx.xx")
                .properties(getVendorProperties())
                .persistenceUnit("firstManageFactory")
                .properties(getVendorProperties())
                .build();
    }

    @Primary
    @Bean(name = "transactionManagerPrimary")
    public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
    }
}
firstJpaConfiguration
技术分享图片
package com.ipinyou.mip.configuration;

import java.util.Map;

import javax.persistence.EntityManager;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
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;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactorySec",
        transactionManagerRef = "transactionManagerSec",
        basePackages = {"xx.xx.xx"})//设置dao(repo)所在位置
public class JpaSecConfiguration {

    @Autowired
    @Qualifier("secDatasource")
    private DataSource secDatasource;
    
    @Bean(name = "entityManagerAmp")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryAmp(builder).getObject().createEntityManager();
    }

    @Autowired
    private JpaProperties jpaProperties;

    private Map<String, Object> getVendorProperties() {
        return jpaProperties.getHibernateProperties(new HibernateSettings());
    }

    /**
     * 设置实体类所在位置
     */
    @Bean(name = "entityManagerFactorySec")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryAmp(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(secDatasource)
                .packages("xx.xx.xx")
                .properties(getVendorProperties())
                .persistenceUnit("secManageFactory")
                .properties(getVendorProperties())
                .build();
    }

    @Bean(name = "transactionManagerSec")
    public PlatformTransactionManager transactionManagerAmp(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactorySec(builder).getObject());
    }
}
secJpaConfiguration
技术分享图片
package com.ipinyou.mip.configuration;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.core.JdbcTemplate;

@Configuration
@Import(DatasourceConfiguration.class)
public class JdbcTemplateConfiguration {
    @Bean(name = "secJdbcTemplate")
    public JdbcTemplate primaryJdbcTemplate(
            @Qualifier("secDatasource") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }


    @Bean(name = "firstJdbcTemplate")
    public JdbcTemplate threeJdbcTemplate(
            @Qualifier("firstDatasource") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}
JdbcTemplateConfiguration
技术分享图片
/**
 * 提供了一系列数据库查询方法
 *
 * @author guodong.zhang
 */
public class CommonDao<E, PK extends Serializable> {

    @PersistenceContext(unitName = "secManageFactory")
    protected EntityManager em;
   /**
     * 相当于jdbctemplate的queryForlist 返回List<Map<String, Object>>
     *
     * @param sql
     * @return
     */
    public List<Map<String, Object>> queryForList(String sql) {
        Query nativeQuery = em.createNativeQuery(sql);
        nativeQuery.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<Map<String,Object>> resultList = nativeQuery.getResultList();
        return resultList;
    }
}
具体使用

 

以上是关于如何使用多数据源,同时使用jpa和jdbctemplate的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Spring Data Jpa 启用多租户

使用spring boot、jpa和security的多用户restful api

如何在多对多关系上使用休眠和 JPA 删除孤立实体?

如何使用更新的 JPA 时间戳字段升级数据库?

如何使用 jpa 存储库查询多对一映射

JPA 2 一对多 - JPA 如何推断列信息?