微服务

SpringBoot2.0+Spring Data Jpa实现多

2019-11-17  本文已影响0人  墨倾心児

Spring Boot中使用的Jpa实际上是Spring Data Jpa,Spring Data是Spring家族的一个子项目,用于简化SQL和NoSQL的访问。
下面来做一下SpringBoot2.0+Spring Data Jpa实现多数据源。

  1. 首先,在application.yml 中做一些DataSource的配置,
spring:
  application:
    name: ms
  jackson:
      date-format: yyyy-MM-dd HH:mm:ss.SSS
      time-zone: GMT+8
  datasource:
    primary:
          type: com.alibaba.druid.pool.DruidDataSource
          jdbc-url: jdbc:mysql://localhost:3306/db1?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
          username : 
          password : 
          driverClassName : com.mysql.cj.jdbc.Driver
    secondary:
          jdbc-url:  jdbc:postgresql://localhost:5432/postgis
          username: 
          password: 
          driverClassName: org.postgresql.Driver
  jpa:
    hibernate:
      primary-dialect: org.hibernate.dialect.MySQL5Dialect
      secondary-dialect: org.hibernate.dialect.PostgreSQL9Dialect
      ddl-auto: update
    show-sql: true
    properties:
      hibernate:
        temp:
          use_jdbc_metadata_defaults: false

use_jdbc_metadata_defaults: false 是为了解决:这个 org.postgresql.jdbc.PgConnection.createClob() 方法尚未被实作。
说明:平常我们配置URL的时候使用spring.datasource.primary.url,但是这里不行了,这么写会报错:jdbcUrl is required with driverClassName。

spring.datasource.url 数据库的 JDBC URL。
spring.datasource.jdbc-url 用来重写自定义连接池
官方文档的解释是:
因为连接池的实际类型没有被公开,所以在您的自定义数据源的元数据中没有生成密钥,而且在IDE中没有完成(因为DataSource接口没有暴露属性)。另外,如果您碰巧在类路径上有Hikari,那么这个基本设置就不起作用了,因为Hikari没有url属性(但是确实有一个jdbcUrl属性)。
因此要改为 spring.datasource.primary.jdbc-url

  1. 编写DataSourceConfig
import javax.sql.DataSource;

/**
 * @create 2019-11-17 12:47
 * @desc 配置多数据源
 **/
@Configuration
public class DataSourceConfig {
    @Bean(name = "primaryDataSource")
    @Primary
    @Qualifier("primaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource primaryDatasource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "secondaryDataSource")
    @Qualifier("secondaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }
}

  1. 编写PrimaryConfig

/**
 * @create 2019-11-17 12:50
 * @desc MySQL数据源的配置
 **/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryPrimary",//配置连接工厂 entityManagerFactory
        transactionManagerRef = "transactionManagerPrimary", //配置 事物管理器  transactionManager
        basePackages = {"xxx.xxx.xxx.xxx.repo"}//设置持久层所在位置
)
public class PrimaryConfig {

    @Autowired
    private Properties jpaProperties;

    @Autowired
    @Qualifier("primaryDataSource")
    private DataSource primaryDataSource;// 自动注入配置好的数据源
   /* @Autowired
    private HibernateProperties hibernateProperties;*/

    @Value("${spring.jpa.hibernate.primary-dialect}")
    private String primaryDialect;// 获取对应的数据库方言

    @Primary
    @Bean(name = "entityManagerPrimary")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
    }
    /**
     *
     * @param builder
     * @return
     */
    @Bean(name = "entityManagerFactoryPrimary")
    @Primary
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {

        LocalContainerEntityManagerFactoryBean entityManagerFactory = builder
                //设置数据源
                .dataSource(primaryDataSource)
                //设置实体类所在位置.扫描所有带有 @Entity 注解的类
                .packages("xxx.xxx.xxx.xxx.entity")
                // Spring会将EntityManagerFactory注入到Repository之中.有了 EntityManagerFactory之后,
                // Repository就能用它来创建 EntityManager 了,然后 EntityManager 就可以针对数据库执行操作
                .persistenceUnit("primaryPersistenceUnit")
                .build();
        entityManagerFactory.setJpaProperties(jpaProperties);
        return entityManagerFactory;
    }


    /**
     * 配置事物管理器
     *
     * @param builder
     * @return
     */
    @Bean(name = "transactionManagerPrimary")
    @Primary
    PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
    }
}

  1. 编写SecondaryConfig
/**
 * @create 2019-11-17 13:01
 * @desc postgresql 数据源的配置
 **/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef="entityManagerFactorySecondary",
        transactionManagerRef="transactionManagerSecondary",
        basePackages= { "xxx.xxx.xxx.xxx.repo" })
public class SecondaryConfig {

    @Autowired
    private Properties jpaProperties;

    @Autowired
    @Qualifier("secondaryDataSource")
    private DataSource secondaryDataSource;
    /*@Autowired
    private HibernateProperties hibernateProperties;*/

    @Value("${spring.jpa.hibernate.secondary-dialect}")
    private String secondaryDialect;



    @Bean(name = "entityManagerSecondary")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactorySecondary(builder).getObject().createEntityManager();
    }

    @Bean(name = "entityManagerFactorySecondary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) {
        LocalContainerEntityManagerFactoryBean entityManagerFactory = builder
                .dataSource(secondaryDataSource)
                .packages("xxx.xxx.xxx.xxx.entity")
                .persistenceUnit("secondaryPersistenceUnit")
                .build();
        entityManagerFactory.setJpaProperties(jpaProperties);
        return entityManagerFactory;
    }
    /*
        private Map<String, String> getVendorProperties(DataSource dataSource) {
            Map<String,String> map = new HashMap<>();
            map.put("hibernate.dialect",secondaryDialect);
            jpaProperties.setProperties(map);
            return jpaProperties.getHibernateProperties(dataSource);
        }*/
    //spring boot 2.1以上版本应该这么写  JPA多数据源配置
    /*@Bean(name = "entityManagerFactorySecondary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary(
            EntityManagerFactoryBuilder builder, JpaProperties jpaProperties,
            HibernateProperties hibernateProperties) {
        Map<String, Object> properties = hibernateProperties.determineHibernateProperties(
                jpaProperties.getProperties(), new HibernateSettings());
        return builder.dataSource(secondaryDataSource).properties(properties)
                .packages("com.jcloud.traffic.situation.postgis.entity").build();
    }*/


    @Bean(name = "transactionManagerSecondary")
    PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
    }


}
  1. 测试,写好相关数据库中对应的entity和repository,写几个service作为测试
/**
 * @create 2019-11-16 16:08
 * @desc
 **/
@RestController
public class DemoController {
    @Autowired
    private DemoService demoService;
    @Autowired
    private TestService tstService;
    @GetMapping("/test")
    public Map te(){
        User u = demoService.findByid("17");
        
        List<Object> byId = tstService.getById(1L);
        
        Map map=new HashMap(2);
        map.put("user",u);
        map.put("byId",byId);
        return map;
    }
}

postman访问接口,查看结果

{
    "code": 0,
    "message": "",
    "data": {
        "byId": [
            {
                "id": 1,
                "city": "杭州市",
                "date": 1549987200000,
                "time": 43557000,
                .......
            }
        ],
        "user": {
            "gid": 787,
            "id": 17,
            "type": 2,
            .......
        }
    }
}

6.补充一些依赖

<dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
       </dependency>
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <version>1.16.18</version>
       </dependency>

<dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-tx</artifactId>
           <!--<version>5.1.9.RELEASE</version>-->
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-data-jpa</artifactId>
       </dependency>

       <!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
       <dependency>
           <groupId>org.postgresql</groupId>
           <artifactId>postgresql</artifactId>
           <version>42.2.5</version>
       </dependency>
       <!-- MySQL 驱动, 注意, 这个需要与 MySQL 版本对应 -->
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>8.0.12</version>
           <scope>runtime</scope>
       </dependency>

       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-autoconfigure</artifactId>
           <version>2.0.2.RELEASE</version>
       </dependency>
       <!-- druid 连接池 -->
       <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>druid</artifactId>
           <version>1.1.13</version>
       </dependency>
       <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>druid-spring-boot-starter</artifactId>
           <version>1.1.13</version>
       </dependency>
       <dependency>
           <groupId>log4j</groupId>
           <artifactId>log4j</artifactId>
           <version>1.2.17</version>
       </dependency>
       <!-- sql 日志待参数输出 -->
       <dependency>
           <groupId>com.googlecode.log4jdbc</groupId>
           <artifactId>log4jdbc</artifactId>
           <version>1.2</version>
       </dependency>


上一篇下一篇

猜你喜欢

热点阅读