spring data jpa 环境搭建(多DB)

  • pom依赖


    org.springframework.boot
    spring-boot-starter-data-jpa



    mysql
    mysql-connector-java
    runtime

  • spring boot 多数据源配置
#数据源配置 mysql8 使用com.mysql.cj.jdbc.Driver驱动,PS:serverTimezone=GMT需要加上,不然服务器时间不能同步
spring.datasource.test.driver-class-name=com.mysql.cj.jdbc.Driver
#新版本mysql,必须带上时区说明serverTimezone=GMT
#GMT会少了8小时,所以这里用GMT+8,转义后:GMT%2b8
spring.datasource.test.jdbc-url=jdbc\:mysql\://localhost\:3306/test?serverTimezone\=GMT%2b8&autoReconnect\=true&useUnicode\=true&characterEncoding\=UTF-8&useSSL\=true 
spring.datasource.test.username=root
spring.datasource.test.password=
spring.datasource.test.max-idle=10
spring.datasource.test.max-wait=10000
spring.datasource.test.min-idle=5
spring.datasource.test.initial-size=5

#本地 订单数据源配置
spring.datasource.order.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.order.jdbc-url=jdbc\:mysql\://localhost\:3306/order?serverTimezone\=GMT%2b8&autoReconnect\=true&useUnicode\=true&characterEncoding\=UTF-8&useSSL\=true 
spring.datasource.order.username=root
spring.datasource.order.password=
spring.datasource.order.max-idle=10
spring.datasource.order.max-wait=10000
spring.datasource.order.min-idle=5
spring.datasource.order.initial-size=5
#1.251 业务数据源配置
spring.datasource.report.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.report.jdbc-url=jdbc\:mysql\://192.168.1.251\:3306/gnota?serverTimezone\=GMT%2b8&autoReconnect\=true&useUnicode\=true&characterEncoding\=UTF-8&useSSL\=true 
spring.datasource.report.username=root
spring.datasource.report.password=
spring.datasource.report.max-idle=10
spring.datasource.report.max-wait=10000
spring.datasource.report.min-idle=5
spring.datasource.report.initial-size=5
  • spring boot jpa 配置
#SQL输出
spring.jpa.show-sql=true
#spring.jpa.properties.hibernate.hbm2ddl.auto说明
#create:Hibernate每次删除上次生成,然后根据实体重新生成表,哪怕实体没有变化也照样执行。
#create-drop:Hibernate每次根据实体生成表,sessionFactory关闭,表自动删除。
#update:比较常用,先建好数据库,Hibernate第一次根据实体自动建表,后面根据实体说明结构自动更新表结构,表一直存在。PS:发布服务器后,服务器启动不会立马执行,得到app调用
#validate:Hibernate每次验证创建数据库表结构,只会和数据库中的表进比较,不会创建新表,但是会插入新值。
spring.jpa.properties.hibernate.hbm2ddl.auto=update
#新版mysql方言MySQL5InnoDBDialect
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
#format SQL进⾏输出
spring.jpa.properties.hibernate.format_sql=true
#jpa多数据源配置后调用autoware dao接口可能会报相同bean名冲突
#2种方法可以解决,打开spring.main.allow-bean-definition-overriding或在springboot启动类添加注解
#@ComponentScan(nameGenerator = AnnotationBeanNameGenerator.class)
#如果junit测试,在类头部也要加上该注解
#这里用注解解决相同名bean冲突,所以注释了allow-bean-definition-overriding
#相同bean名覆盖注册 SpringBoot 2.1之前,这个配置默认就是true,而在2.1做了更改。
#spring.main.allow-bean-definition-overriding=true
  • 针对不同数据源配置生成对应的DataSource的Configuration
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
/**
 *     数据集源配置,此示例配置了3个数据源
*1,spring.datasource.test
*2,spring.datasource.order
*3,spring.datasource.report
* 通过配置文件中的前缀,区分数据源 * @author kyoxue * @date 2019年10月28日 */ @Configuration public class DemoDBConfiguration { /** 定义数据源 */ //默认数据源 @Primary //bean名称 @Bean(name="orderDB") //为数据源取别名区分 @Qualifier("orderDB") //指定配置数据源前缀 @ConfigurationProperties("spring.datasource.order") public DataSource orderDB() { return DataSourceBuilder.create().build(); } //bean名称 @Bean(name="reportDB") //为数据源取别名区分 @Qualifier("reportDB") //指定配置数据源前缀 @ConfigurationProperties("spring.datasource.report") public DataSource reportDB() { return DataSourceBuilder.create().build(); } //bean名称 @Bean(name="testDB") //为数据源取别名区分 @Qualifier("testDB") //指定配置数据源前缀 @ConfigurationProperties("spring.datasource.test") public DataSource testDB() { return DataSourceBuilder.create().build(); } }
  • 使用对应的DataSource生成JPA对应的配置
    主要工作内容:
    1.通过DataSource的bean实例,实体对象的包路径来产生对应该数据源的jpa环境
    2.生成JPA的对应api接口EntityManager
    3.生成对应数据源的事务PlatformTransactionManager

有一定注意:EntityManagerFactoryBuilder此处的包路径为org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder
而非org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder
orderDB对应的JPA配置

package com.example.demo;

import java.util.Map;

import javax.annotation.Resource;
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.HibernateProperties;
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;
/**
 * 针对localhost:3306/order数据源的JPA配置
 * ps:多数据源,JPA配置类至少有一个,其下所有方法添加primary注解
 * 本示例primary写在test数据源配置中
 * @author kyoxue
 * @date 2019年10月30日
 */
//标识此为spring bean 配置类,启动时加载
@Configuration
//启用事务支持
@EnableTransactionManagement
@EnableJpaRepositories(
        //JPA数据访问环境
        entityManagerFactoryRef="localContainerEntityManagerFactoryBeanOrder",
        //JPA事务
        transactionManagerRef="transactionManagerOrder",
        //dao接口包扫描
        basePackages={"com.example.demo.dao.order"})
public class DemoJPAOrderConfiguration {
    //引入orderDB数据源,别名orderDB与DemoDBConfiguration中@Qualifier("orderDB")一致
        //注意:@Qualifier不可少,否则导致不能准确区分数据源
    @Autowired
    @Qualifier("orderDB")
    private DataSource orderDB;
    @Autowired
    private JpaProperties jpaProperties;
    @Resource
    private HibernateProperties hibernateProperties;
    
    private Map getVendorProperties() {
        return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
    }
    /**
     * 创建JPA数据访问环境
     * @param entityManagerFactoryBuilder
     * @return
     */
    @Bean(name="localContainerEntityManagerFactoryBeanOrder")
    public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanOrder(org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder entityManagerFactoryBuilderOrder) {
        return entityManagerFactoryBuilderOrder
        //数据源
        .dataSource(orderDB)
        //JPA配置信息
        .properties(getVendorProperties())
        //实体类的包路径
        .packages("com.example.demo.entity.order")
        //JPA数据环境名称定义
        .persistenceUnit("persistenceUnitOrder")
        .build();
    }
    /**
     * 操控数据库的对应API
     * EntityManager是JPA中⽤于增、删、改、查的接⼝
     * ,它的作⽤相当于⼀座桥梁
     * ,连接内存中的Java对象 和数据库的数据存储。
     *    使⽤EntityManager中的相关接⼝对数据库实体进⾏操作的时候
     * ,EntityManager会跟踪实体对象的状态
     * ,并决定在特定时刻将对实体的操作映射到数据库操作上⾯
     * @param entityManagerFactoryBuilderOrder
     * @return
     */
    @Bean(name="entityManagerOrder")
    public EntityManager entityManagerOrder(org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder entityManagerFactoryBuilderOrder){
        return localContainerEntityManagerFactoryBeanOrder(entityManagerFactoryBuilderOrder).getObject().createEntityManager();
    }
    /**
     * 给数据源添加JPA事务
     * @param entityManagerFactoryBuilderOrder
     * @return
     */
    @Bean(name="transactionManagerOrder")
    PlatformTransactionManager transactionManagerOrder(EntityManagerFactoryBuilder entityManagerFactoryBuilderOrder){
        return new JpaTransactionManager(localContainerEntityManagerFactoryBeanOrder(entityManagerFactoryBuilderOrder).getObject());
    }
}

reportDB对应的JPA配置

package com.example.demo;

import java.util.Map;

import javax.annotation.Resource;
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.HibernateProperties;
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;
/**
 * 针对192.168.1.251:3306/gnota数据源的JPA配置
 * ps:多数据源,JPA配置类至少有一个,其下所有方法添加primary注解
 * 本示例primary写在test数据源配置中
 * @author kyoxue
 * @date 2019年10月30日
 */
//标识此为spring bean 配置类,启动时加载
@Configuration
//启用事务支持
@EnableTransactionManagement
@EnableJpaRepositories(
        //JPA数据访问环境
        entityManagerFactoryRef="localContainerEntityManagerFactoryBeanReport",
        //JPA事务
        transactionManagerRef="transactionManagerReport",
        //dao接口包扫描
        basePackages={"com.example.demo.dao.report"})
public class DemoJPAReportConfiguration {
    //引入reportDB数据源,属性名reportDB与DemoDBConfiguration中@Qualifier("reportDB")一致
    @Autowired
    @Qualifier("reportDB")
    private DataSource reportDB;
    @Autowired
    private JpaProperties jpaProperties;
    @Resource
    private HibernateProperties hibernateProperties;
    
    private Map getVendorProperties() {
        return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
    }
    /**
     * 创建JPA数据访问环境
     * @param entityManagerFactoryBuilder
     * @return
     */
    @Bean(name="localContainerEntityManagerFactoryBeanReport")
    public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanReport(org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder entityManagerFactoryBuilderReport) {
        return entityManagerFactoryBuilderReport
        //数据源
        .dataSource(reportDB)
        //JPA配置信息
        .properties(getVendorProperties())
        //实体类的包路径
        .packages("com.example.demo.entity.report")
        //JPA数据环境名称定义
        .persistenceUnit("persistenceUnitReport")
        .build();
    }
    /**
     * 操控数据库的对应API
     * EntityManager是JPA中⽤于增、删、改、查的接⼝
     * ,它的作⽤相当于⼀座桥梁
     * ,连接内存中的Java对象 和数据库的数据存储。
     *    使⽤EntityManager中的相关接⼝对数据库实体进⾏操作的时候
     * ,EntityManager会跟踪实体对象的状态
     * ,并决定在特定时刻将对实体的操作映射到数据库操作上⾯
     * @param entityManagerFactoryBuilderReport
     * @return
     */
    @Bean(name="entityManagerReport")
    public EntityManager entityManagerReport(org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder entityManagerFactoryBuilderReport){
        return localContainerEntityManagerFactoryBeanReport(entityManagerFactoryBuilderReport).getObject().createEntityManager();
    }
    /**
     * 给数据源添加JPA事务
     * @param entityManagerFactoryBuilderReport
     * @return
     */
    @Bean(name="transactionManagerReport")
    PlatformTransactionManager transactionManagerReport(EntityManagerFactoryBuilder entityManagerFactoryBuilderReport){
        return new JpaTransactionManager(localContainerEntityManagerFactoryBeanReport(entityManagerFactoryBuilderReport).getObject());
    }
}

testDB对应的JPA配置,注意一点:testDB这个JPA配置类每个bean方法都加了@Primary注解,可以任意一个配置类加@Primary注解,其余不用,但至少有一个配置类是这样的

package com.example.demo;

import java.util.Map;

import javax.annotation.Resource;
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.HibernateProperties;
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;
/**
 * 针对localhost:3306/test数据源的JPA配置
 * ps:多数据源,JPA配置类至少有一个,其下所有方法添加primary注解
 * @author kyoxue
 * @date 2019年10月30日
 */
//标识此为spring bean 配置类,启动时加载
@Configuration
//启用事务支持
@EnableTransactionManagement
@EnableJpaRepositories(
        //JPA数据访问环境
        entityManagerFactoryRef="localContainerEntityManagerFactoryBeanTest",
        //JPA事务
        transactionManagerRef="transactionManagerTest",
        //dao接口包扫描
        basePackages={"com.example.demo.dao.test"})
public class DemoJPATestConfiguration {
    //引入testDB数据源,属性名testDB与DemoDBConfiguration中@Qualifier("testDB")一致
    @Autowired
    @Qualifier("testDB")
    private DataSource testDB;
    @Autowired
    private JpaProperties jpaProperties;
    @Resource
    private HibernateProperties hibernateProperties;
    
    private Map getVendorProperties() {
        return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
    }
    /**
     * 创建JPA数据访问环境
     * @param entityManagerFactoryBuilder
     * @return
     */
    @Bean(name="localContainerEntityManagerFactoryBeanTest")
    @Primary
    public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanTest(org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder entityManagerFactoryBuilderTest) {
        return entityManagerFactoryBuilderTest
        //数据源
        .dataSource(testDB)
        //JPA配置信息
        .properties(getVendorProperties())
        //实体类的包路径
        .packages("com.example.demo.entity.test")
        //JPA数据环境名称定义
        .persistenceUnit("persistenceUnitTest")
        .build();
    }
    /**
     * 操控数据库的对应API
     * EntityManager是JPA中⽤于增、删、改、查的接⼝
     * ,它的作⽤相当于⼀座桥梁
     * ,连接内存中的Java对象 和数据库的数据存储。
     *    使⽤EntityManager中的相关接⼝对数据库实体进⾏操作的时候
     * ,EntityManager会跟踪实体对象的状态
     * ,并决定在特定时刻将对实体的操作映射到数据库操作上⾯
     * @param entityManagerFactoryBuilderTest
     * @return
     */
    @Bean(name="entityManagerTest")
    @Primary 
    public EntityManager entityManagerTest(org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder entityManagerFactoryBuilderTest){
        return localContainerEntityManagerFactoryBeanTest(entityManagerFactoryBuilderTest).getObject().createEntityManager();
    }
    /**
     * 给数据源添加JPA事务
     * @param entityManagerFactoryBuilderTest
     * @return
     */
    @Bean(name="transactionManagerTest")
    @Primary 
    PlatformTransactionManager transactionManagerTest(EntityManagerFactoryBuilder entityManagerFactoryBuilderTest){
        return new JpaTransactionManager(localContainerEntityManagerFactoryBeanTest(entityManagerFactoryBuilderTest).getObject());
    }
}

  • 对应配置中包位置建立dao接口已经实体类
  1. testDB


    image.png

    image.png
  2. orderDB


    image.png

    image.png
  3. reportDB


    image.png

    image.png
  • 对dao以及entity代码如下
/**
 * 继承JpaRepository<实体名称,实体主键类型>,使用其内置大量常用API
 * @author kyoxue
 * @date 2019年10月31日
 */
@Qualifier("testJPA")
public interface TestJPADao extends JpaRepository {

}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity(name="jpa_test")
public class EntityTestJPA {

    @Id
    @GeneratedValue
    private Long id;
    @Column
    private String testName;
    //setter...getter...
}
@Qualifier("orderJPA")
public interface OrderJPADao extends JpaRepository {

}
@Entity(name="jpa_order")
public class EntityOrder {
    @Id
    //主键生成策略GenerationType包括AUTO、INDENTITY、SEQUENCE和TABLE
    //generator主键生成器名称
    @GeneratedValue(strategy=GenerationType.AUTO,generator="order_generator")
    private Long id;
    @Column
    private Date time;
    @Column
    private String orderNo;
    //setter...getter...
}
@Qualifier("reportJPA")
public interface ReportJPADao extends JpaRepository {

}
@Entity(name = "jpa_report")
public class EntityReport {
    @Id
    @GeneratedValue
    private Integer id;
    @Column
    private String reportName;
    //setter...getter...
}
  • junit测试多数据源操作
@RunWith(SpringRunner.class)
//因为项目用到了websocket,这里引入随机端口
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
//相同bean名冲突解决,springboot解决bean命名冲突可以加入这个注解,也可以在配置文件加入spring.main.allow-bean-definition-overriding=true
@ComponentScan(nameGenerator = AnnotationBeanNameGenerator.class)
public class applicationTest {
    @Resource
    private TestJPADao testJPA;
    @Resource
    private OrderJPADao orderJPA;
    @Resource
    private ReportJPADao reportJPA;
    @Test
    public void testEntityTestJPA()throws Exception{
        EntityTestJPA vo = new EntityTestJPA();
        vo.setTestName("ttt1");
        testJPA.save(vo);
    }
    @Test
    public void testEntityOrderJPA()throws Exception{
        EntityOrder vo = new EntityOrder();
        vo.setOrderNo("aaaa");
        vo.setTime(new Date());
        orderJPA.save(vo);
    }
    @Test
    public void testEntityReportJPA()throws Exception{
        EntityReport vo = new EntityReport();
        vo.setReportName("tttttt");
        reportJPA.save(vo);
    }
}
  • 查看数据库是否正确操作
  1. testDB


    image.png
  2. orderDB


    image.png
  3. reportDB


    image.png
  • 至此,多数据源测试完毕。

你可能感兴趣的:(spring data jpa 环境搭建(多DB))