• Spring data JPA的多数据源实现


    一、主流的多数据源支持方式

    将数据源对象作为参数,传递到调用方法内部,这种方式增加额外的编码。如:JDBC多数据源添加方式
    将Repository操作接口分包存放,Spring扫描不同的包,自动注入不同的数据源。这种方式实现简单,也是一种“约定大于配置”思想的典型应用。本文将以这种方式实现JPA的多数据源支持

    二、修改application.yml配置多数据源

    server:
      port: 8098
    spring:
      #通用的数据源配置
      datasource:
        primary:
          driver-class-name: com.mysql.jdbc.Driver
          jdbc-url: jdbc:mysql://123.57.87.54:3306/ssm?useSSL=false&useUnicode=true&characterEncoding=utf8
          username: bms
          password: bms@2018
        secondary:
          driver-class-name: com.mysql.jdbc.Driver
          jdbc-url: jdbc:mysql://123.57.87.54:3306/ssm2?useSSL=false&useUnicode=true&characterEncoding=utf8
          username: bms
          password: bms@2018
      jpa:
        #这个参数是在建表的时候,将默认的存储引擎切换为 InnoDB 用的
        database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
        #配置在日志中打印出执行的 SQL 语句信息。
        show-sql: true
        hibernate:
          #配置指明在程序启动的时候要删除并且创建实体类对应的表
          ddl-auto: validate
    

    三、 两组数据持久化接口及实体类,放到不同的package里面

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    @Entity
    @Table(name ="article")
    public class Article {
    
        @Id
        @GeneratedValue(strategy= GenerationType.IDENTITY)
        private Integer id;
        private String author;
        private String title;
        private String content;
        @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
        private Date createTime;
    }
    
    
    @Repository
    public interface ArticleRepository extends JpaRepository<Article,Integer> {
    }
    
    

    四、第一组JPA数据持久层配置

    配置JPA的数据持久层,需要配置:

    DataSource数据源
    EntityManager 实体管理器
    EntityManagerFactoryBean 实体管理器工厂
    PlatformTransactionManager 事务管理器
    依次把上面的Bean配置并实例化,注入到Spring上下文中即可。或者更简单的说,下面的这段配置就是一个模板配置、固定配置。如果你自己去实现,唯一需要改动的地方就是com.dj.dao.testssm换成你自己的JpaRepository类所在的package路径。

    package com.dj.config;
    
    import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
    import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
    import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.jdbc.DataSourceBuilder;
    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.annotation.Resource;
    import javax.persistence.EntityManager;
    import javax.sql.DataSource;
    import java.util.Map;
    
    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
            entityManagerFactoryRef="entityManagerFactoryPrimary",
            transactionManagerRef="transactionManagerPrimary",
            basePackages= { "com.dj.dao.testssm" }) //换成你自己的Repository所在位置
    public class JPAPrimaryConfig {
    
        @Resource
        private JpaProperties jpaProperties;
    
        @Resource
        private HibernateProperties hibernateProperties;
    
    
        @Primary
        @Bean(name = "primaryDataSource")
        @ConfigurationProperties(prefix="spring.datasource.primary")  //使用application.yml的primary数据源配置
        public DataSource primaryDataSource() {
            return DataSourceBuilder.create().build();
        }
    
        @Primary
        @Bean(name = "entityManagerPrimary")        //primary实体管理器
        public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
            return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
        }
    
        @Primary
        @Bean(name = "entityManagerFactoryPrimary")    //primary实体工厂
        public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
            Map<String,Object> properties =
                    hibernateProperties.determineHibernateProperties(
                            jpaProperties.getProperties(),
                            new HibernateSettings());
            return builder.dataSource(primaryDataSource())
                    .properties(properties)
                    .packages("com.dj.model.modelssm")     //换成你自己的实体类所在位置
                    .persistenceUnit("primaryPersistenceUnit")
                    .build();
        }
    
    
        @Primary
        @Bean(name = "transactionManagerPrimary")         //primary事务管理器
        public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
            return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
        }
    }
    
    
    

    五、第二组JPA数据持久层配置

    因为我们要做双数据源、所以仿造上面的第一组配置,再写一组配置。区别是:

    没有@Primary注解,因为这一组配置不是默认配置,该组数据源不是默认数据源。这个注解前面章节也讲过。
    注意本组的Repository扫描路径是com.dj.model.modelssm2,不是modelssm

    package com.dj.config;
    
    import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
    import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
    import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.jdbc.DataSourceBuilder;
    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.annotation.Resource;
    import javax.persistence.EntityManager;
    import javax.sql.DataSource;
    import java.util.Map;
    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
            entityManagerFactoryRef="entityManagerFactorySecondary",
            transactionManagerRef="transactionManagerSecondary",
            basePackages= { "com.dj.dao.testssm2" }) //换成你自己的Repository所在位置
    public class JPASecondaryConfig {
    
        @Resource
        private JpaProperties jpaProperties;
    
        @Resource
        private HibernateProperties hibernateProperties;
    
    
        @Bean(name = "secondaryDataSource")
        @ConfigurationProperties(prefix="spring.datasource.secondary")   //使用application.yml的secondary数据源配置
        public DataSource secondaryDataSource() {
            return DataSourceBuilder.create().build();
        }
    
        @Bean(name = "entityManagerSecondary")      //secondary实体管理器
        public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
            return entityManagerFactorySecondary(builder).getObject().createEntityManager();
    
        }
    
    
    
        @Bean(name = "entityManagerFactorySecondary")
        public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) {
    
            Map<String,Object> properties =
                    hibernateProperties.determineHibernateProperties(
                            jpaProperties.getProperties(),
                            new HibernateSettings());
    
            return builder
                    .dataSource(secondaryDataSource())
                    .properties(properties)
                    .packages("com.dj.model.modelssm2") //换成你自己的实体类所在位置
                    .persistenceUnit("secondaryPersistenceUnit")
                    .build();
        }
    
    
        @Bean(name = "transactionManagerSecondary")
        PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
            return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
    
        }
    
    }
    
    

    六、测试

    package com.dj;
    
    import com.dj.dao.testssm.ArticleRepository;
    import com.dj.dao.testssm2.UserRepository;
    import com.dj.model.modelssm.Article;
    import com.dj.model.modelssm2.User;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.util.Date;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class SpringBootjpaTest {
    
        @Autowired
        private ArticleRepository articleRepository;
        @Autowired
        private UserRepository userRepository;
    
        @Test
        public void jpaTest(){
            Article article = Article.builder()
                    .id(25)
                    .author("zimug")
                    .content("spring boot 从青铜到王者")
                    .createTime(new Date())
                    //.reader(readers)
                    .title("t133333").build();
    
            User user = User.builder()
                    .user_name("zimug")
                    .address("ok")
                    .birthday(new Date())
                    .sex("南")
                    .build();
    
            //先构造一个Article对象article,这个操作针对testdb
            articleRepository.save(article);
            //在构造一个Message对象message,这个操作针对testdb2
            userRepository.save(user);
        }
    }
    
    

    源码地址
    参考链接:https://www.kancloud.cn/hanxt/springboot2/1177606

  • 相关阅读:
    二分查找练习
    Linux中Buffer和Cache的区别
    c++设计模式之单例模式
    c++设计模式之工厂模式
    C++中内存泄漏的几种情况
    snprintf
    命名空间和模块化编程1
    避免内存泄漏
    静态对象强制类型转换
    副本构造器
  • 原文地址:https://www.cnblogs.com/weidaijie/p/14336776.html
Copyright © 2020-2023  润新知