• Spring Data JPA 多数据源并支持多数据源事务


    application.yml 配置

    com.seliote.twowaysync:
      datasource:
        zg:
          url: jdbc:mysql://192.168.0.1:3306/jd4?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&autoReconnect=true
          username: root
          password: 6125@hdynhjs
          driver: com.mysql.cj.jdbc.Driver
          hikari:
            maximum-pool-size: 200
            connection-timeout: 5000
            max-lifetime: 1800000
            minimum-idle: 5
            idle-timeout: 300000
            connection-test-query: SELECT 1
            dialect: org.hibernate.dialect.MySQLInnoDBDialect
        jd:
          url: jdbc:mysql://192.168.0.1:3306/jd3?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&autoReconnect=true
          username: root
          password: 6125@hdynhjs
          driver: com.mysql.cj.jdbc.Driver
          hikari:
            maximum-pool-size: 200
            connection-timeout: 5000
            max-lifetime: 1800000
            minimum-idle: 5
            idle-timeout: 300000
            connection-test-query: SELECT 1
            dialect: org.hibernate.dialect.MySQLInnoDBDialect
        tws:
          url: jdbc:mysql://192.168.0.1:3306/tws?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&autoReconnect=true
          username: root
          password: 6125@hdynhjs
          driver: com.mysql.cj.jdbc.Driver
          hikari:
            maximum-pool-size: 200
            connection-timeout: 5000
            max-lifetime: 1800000
            minimum-idle: 5
            idle-timeout: 300000
            connection-test-query: SELECT 1
            dialect: org.hibernate.dialect.MySQLInnoDBDialect
    

    对应的配置注入类:

    package com.seliote.twowaysync.config;
    
    import lombok.Getter;
    import lombok.Setter;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    
    /**
     * Yaml 配置
     *
     * @author Li Yangdi
     * @since 2022-04-16
     */
    @Slf4j
    @Getter
    @Setter
    @Component
    @ConfigurationProperties(prefix = "com.seliote.twowaysync")
    public class YmlConfig {
    
        private DatasourceConfig datasource = new DatasourceConfig();
        private ThreadPoolConfig threadPool = new ThreadPoolConfig();
    
        @Getter
        @Setter
        public static class DatasourceConfig {
            private DatasourceItemConfig zg = new DatasourceItemConfig();
            private DatasourceItemConfig jd = new DatasourceItemConfig();
            private DatasourceItemConfig tws = new DatasourceItemConfig();
    
            @Getter
            @Setter
            public static class DatasourceItemConfig {
                private String url;
                private String username;
                private String password;
                private String driver;
                private HikariConfig hikari;
            }
    
            @Getter
            @Setter
            public static class HikariConfig {
                private Integer maximumPoolSize;
                private Long connectionTimeout;
                private Long maxLifetime;
                private Integer minimumIdle;
                private Long idleTimeout;
                private String connectionTestQuery;
                private String dialect;
            }
        }
    
        @Getter
        @Setter
        public static class ThreadPoolConfig {
            private Integer poolSize;
        }
    }
    

    数据源相关工具类

    package com.seliote.twowaysync.util;
    
    import com.seliote.twowaysync.config.YmlConfig;
    import com.zaxxer.hikari.HikariDataSource;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.orm.jpa.JpaTransactionManager;
    import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
    import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
    import org.springframework.transaction.PlatformTransactionManager;
    
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.SharedCacheMode;
    import javax.persistence.ValidationMode;
    import javax.sql.DataSource;
    import java.util.HashMap;
    
    /**
     * 数据源工具
     *
     * @author Li Yangdi
     * @since 2022-04-16
     */
    @Slf4j
    public class DatasourceUtils {
    
        /**
         * 创建 HikariDataSource
         *
         * @param dataName 数据名
         * @param config   配置
         * @return HikariDataSource 对象
         */
        public static HikariDataSource getDataSource(String dataName,
                                                     YmlConfig.DatasourceConfig.DatasourceItemConfig config) {
            var hikariConfig = new com.zaxxer.hikari.HikariConfig();
            hikariConfig.setPoolName("[" + dataName.toUpperCase() + "-HIKARI-POOL]");
            hikariConfig.setJdbcUrl(config.getUrl());
            hikariConfig.setUsername(config.getUsername());
            hikariConfig.setPassword(config.getPassword());
            hikariConfig.setDriverClassName(config.getDriver());
            hikariConfig.setMaximumPoolSize(config.getHikari().getMaximumPoolSize());
            hikariConfig.setConnectionTimeout(config.getHikari().getConnectionTimeout());
            hikariConfig.setMaxLifetime(config.getHikari().getMaxLifetime());
            hikariConfig.setMinimumIdle(config.getHikari().getMinimumIdle());
            hikariConfig.setIdleTimeout(config.getHikari().getIdleTimeout());
            hikariConfig.setConnectionTestQuery(config.getHikari().getConnectionTestQuery());
            var hikariDatasource = new HikariDataSource(hikariConfig);
            log.debug("Create {} datasource", dataName);
            return hikariDatasource;
        }
    
        /**
         * 创建 EntityManagerFactory
         *
         * @param dataSource   数据源 Datasource
         * @param dialect      Hibernate 方言
         * @param scanPackages 扫描的包
         * @return LocalContainerEntityManagerFactoryBean 对象
         */
        public static LocalContainerEntityManagerFactoryBean getEntityManagerFactory(DataSource dataSource,
                                                                                     String dialect,
                                                                                     String... scanPackages) {
            var props = new HashMap<String, Object>();
            props.put("javax.persistence.schema-generation.database.action", "none");
            var jpaVendorAdapter = new HibernateJpaVendorAdapter();
            jpaVendorAdapter.setDatabasePlatform(dialect);
            var entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
            entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter);
            entityManagerFactory.setDataSource(dataSource);
            entityManagerFactory.setPackagesToScan(scanPackages);
            entityManagerFactory.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE);
            entityManagerFactory.setValidationMode(ValidationMode.NONE);
            entityManagerFactory.setJpaPropertyMap(props);
            log.debug("Create EntityManagerFactory for '{}' by dialect {}",
                    String.join(", ", scanPackages), dialect);
            return entityManagerFactory;
        }
    
        /**
         * 创建 PlatformTransactionManager
         *
         * @param entityManagerFactory EntityManagerFactory 对象
         * @return PlatformTransactionManager 对象
         */
        public static PlatformTransactionManager getTransactionManager(EntityManagerFactory entityManagerFactory) {
            log.debug("Create TransactionManager");
            return new JpaTransactionManager(entityManagerFactory);
        }
    }
    

    数据源 1

    package com.seliote.twowaysync.config;
    
    import com.seliote.twowaysync.util.DatasourceUtils;
    import com.zaxxer.hikari.HikariDataSource;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.AdviceMode;
    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.LocalContainerEntityManagerFactoryBean;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    /**
     * 机电数据源
     *
     * @author Li Yangdi
     * @since 2022-04-16
     */
    @Configuration
    @EnableTransactionManagement(mode = AdviceMode.PROXY)
    @EnableJpaRepositories(
            basePackages = {"com.seliote.twowaysync.repo.jd"},
            entityManagerFactoryRef = "jdEntityManagerFactory",
            transactionManagerRef = "jdTransactionManager"
    )
    public class JdDataSourceConfig {
    
        private YmlConfig.DatasourceConfig.DatasourceItemConfig jdDatasourceConfig;
    
        @Autowired
        public void setDatasourceItemConfig(YmlConfig ymlConfig) {
            this.jdDatasourceConfig = ymlConfig.getDatasource().getJd();
        }
    
        /**
         * 综管 Datasource Bean
         *
         * @return HikariDataSource 对象
         */
        @Primary
        @Bean(name = "jdDataSource")
        public HikariDataSource jdDataSource() {
            return DatasourceUtils.getDataSource("jd", jdDatasourceConfig);
        }
    
        /**
         * 综管 EntityManagerFactory Bean
         *
         * @return LocalContainerEntityManagerFactoryBean 对象
         */
        @Primary
        @Bean(name = "jdEntityManagerFactory")
        public LocalContainerEntityManagerFactoryBean jdEntityManagerFactory() {
            return DatasourceUtils.getEntityManagerFactory(jdDataSource(),
                    jdDatasourceConfig.getHikari().getDialect(),
                    "com.seliote.twowaysync.entity.jd");
        }
    
        /**
         * 综管 PlatformTransactionManager Bean
         *
         * @return PlatformTransactionManager 对象
         */
        @Primary
        @Bean("jdTransactionManager")
        public PlatformTransactionManager jdTransactionManager() {
            return DatasourceUtils.getTransactionManager(jdEntityManagerFactory().getObject());
        }
    }
    

    数据源 2

    package com.seliote.twowaysync.config;
    
    import com.seliote.twowaysync.util.DatasourceUtils;
    import com.zaxxer.hikari.HikariDataSource;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.AdviceMode;
    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.LocalContainerEntityManagerFactoryBean;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    /**
     * 综管数据源
     *
     * @author Li Yangdi
     * @since 2022-04-16
     */
    @Configuration
    @EnableTransactionManagement(mode = AdviceMode.PROXY)
    @EnableJpaRepositories(
            basePackages = {"com.seliote.twowaysync.repo.zg"},
            entityManagerFactoryRef = "zgEntityManagerFactory",
            transactionManagerRef = "zgTransactionManager"
    )
    public class ZgDataSourceConfig {
    
        private YmlConfig.DatasourceConfig.DatasourceItemConfig zgDatasourceConfig;
    
        @Autowired
        public void setDatasourceItemConfig(YmlConfig ymlConfig) {
            this.zgDatasourceConfig = ymlConfig.getDatasource().getZg();
        }
    
        /**
         * 综管 Datasource Bean
         *
         * @return HikariDataSource 对象
         */
        @Bean(name = "zgDataSource")
        public HikariDataSource zgDataSource() {
            return DatasourceUtils.getDataSource("zg", zgDatasourceConfig);
        }
    
        /**
         * 综管 EntityManagerFactory Bean
         *
         * @return LocalContainerEntityManagerFactoryBean 对象
         */
        @Bean(name = "zgEntityManagerFactory")
        public LocalContainerEntityManagerFactoryBean zgEntityManagerFactory() {
            return DatasourceUtils.getEntityManagerFactory(zgDataSource(),
                    zgDatasourceConfig.getHikari().getDialect(),
                    "com.seliote.twowaysync.entity.zg");
        }
    
        /**
         * 综管 PlatformTransactionManager Bean
         *
         * @return PlatformTransactionManager 对象
         */
        @Bean("zgTransactionManager")
        public PlatformTransactionManager zgTransactionManager() {
            return DatasourceUtils.getTransactionManager(zgEntityManagerFactory().getObject());
        }
    }
    

    数据源 3:

    package com.seliote.twowaysync.config;
    
    import com.seliote.twowaysync.util.DatasourceUtils;
    import com.zaxxer.hikari.HikariDataSource;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.AdviceMode;
    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.LocalContainerEntityManagerFactoryBean;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    /**
     * 双向同步数据源
     *
     * @author Li Yangdi
     * @since 2022-04-18
     */
    @Configuration
    @EnableTransactionManagement(mode = AdviceMode.PROXY)
    @EnableJpaRepositories(
            basePackages = {"com.seliote.twowaysync.repo.tws"},
            entityManagerFactoryRef = "twsEntityManagerFactory",
            transactionManagerRef = "twsTransactionManager"
    )
    public class TwsDataSourceConfig {
    
        private YmlConfig.DatasourceConfig.DatasourceItemConfig twsDatasourceConfig;
    
        @Autowired
        public void setDatasourceItemConfig(YmlConfig ymlConfig) {
            this.twsDatasourceConfig = ymlConfig.getDatasource().getTws();
        }
    
        /**
         * 综管 Datasource Bean
         *
         * @return HikariDataSource 对象
         */
        @Bean(name = "twsDataSource")
        public HikariDataSource twsDataSource() {
            return DatasourceUtils.getDataSource("tws", twsDatasourceConfig);
        }
    
        /**
         * 综管 EntityManagerFactory Bean
         *
         * @return LocalContainerEntityManagerFactoryBean 对象
         */
        @Bean(name = "twsEntityManagerFactory")
        public LocalContainerEntityManagerFactoryBean twsEntityManagerFactory() {
            return DatasourceUtils.getEntityManagerFactory(twsDataSource(),
                    twsDatasourceConfig.getHikari().getDialect(),
                    "com.seliote.twowaysync.entity.tws");
        }
    
        /**
         * 综管 PlatformTransactionManager Bean
         *
         * @return PlatformTransactionManager 对象
         */
        @Bean("twsTransactionManager")
        public PlatformTransactionManager twsTransactionManager() {
            return DatasourceUtils.getTransactionManager(twsEntityManagerFactory().getObject());
        }
    }
    

    不同包下的不同实体不同仓库,自动使用不同数据源

  • 相关阅读:
    【k8s】pv 处在 Terminating 状态
    【k8s】命令行自动补全
    【k8s】允许 master 节点运行 pod
    【k8s】Harbor 安装
    Nginx 允许 frame 嵌套
    Python基础教程:json中load和loads区别
    Python 基础教程:用户交互语句
    Python正则表达式-常用函数的基本使用
    Python字典循环与字典排序
    4道Python文件操作和函数练习题
  • 原文地址:https://www.cnblogs.com/seliote/p/16160815.html
Copyright © 2020-2023  润新知