欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring Data JPA中多数据源的配置

程序员文章站 2022-06-09 20:18:17
1、添加多数据源的配置1.1、yaml配置server: port: 40300spring: application: name: jpa-multi-datasource datasource: primary: jdbc-url: jdbc:mysql://148.70.153.63:3306/ttms?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&u...

1、添加多数据源的配置

1.1、yaml配置

server:
  port: 40300

spring:
  application:
    name: jpa-multi-datasource
  datasource:
    primary:
      jdbc-url: jdbc:mysql://148.70.153.63:3306/ttms?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
      username: root
      password: password
      driver-class-name: com.mysql.cj.jdbc.Driver
      initialSize: 5
      maxActive: 50
      minIdle: 0
      maxWait: 60000
      useUnfairLock: true # 禁用公平锁
    secondary:
      jdbc-url: jdbc:mysql://148.70.153.63:3306/ttms?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
      username: root
      password: password
      driver-class-name: com.mysql.cj.jdbc.Driver
      initialSize: 3
      maxActive: 10
      minIdle: 0
      maxWait: 60000
      useUnfairLock: true # 禁用公平锁
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update
    database: MYSQL

注意:

  1. 这里为了方便,2个数据源的配置是用同一个数据库。
  2. 如果使用默认的数据源,在SpringBoot2.x以后需要使用jdbc-url而非url,否则会报 java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName.

1.2、数据源配置

@Configuration
public class DataSourceConfig {
    @Primary
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

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

数据源使用的是SpringBoot2.x版本默认的HikariCP连接池。@Primary注解指定了主数据源。

1.3、JPA配置

1.3.1、Primary数据源的JPA配置
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef="entityManagerFactoryPrimary",
        transactionManagerRef="transactionManagerPrimary",
        basePackages= { "net.zhaoxiaobin.jpa.dao.primary" }) //设置Repository所在位置
public class PrimaryConfig {
    @Autowired
    private DataSource primaryDataSource;

    @Autowired
    private JpaProperties jpaProperties;
    @Autowired
    private HibernateProperties hibernateProperties;

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

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

    @Primary
    @Bean(name = "entityManagerFactoryPrimary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
        return builder.dataSource(primaryDataSource)
                .packages("net.zhaoxiaobin.jpa.domain.primary") //设置实体类所在位置
                .persistenceUnit("primaryPersistenceUnit")
                .properties(getVendorProperties())
                .build();
    }

    @Primary
    @Bean(name = "transactionManagerPrimary")
    public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
    }
}

Repository配置:

public interface PrimaryRepository extends JpaRepository<Actor,Long> {

}

实体类配置:

@Entity
@Table(name = "actor")
@Data
public class Actor {
    /**
     * 主键生成采用数据库自增方式,比如MySQL的AUTO_INCREMENT
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "actor_name", nullable = false, length = 128, unique = true)
    private String actorName;

    @Column(name = "actor_age", nullable = false)
    private int actorAge;

    @Column(name = "actor_email", length = 64, unique = true)
    private String actorEmail;

    @Column(name = "create_time", nullable = false, length = 32)
    private String createTime = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss SSS");
}
1.3.2、Secondary数据源的JPA配置
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef="entityManagerFactorySecondary",
        transactionManagerRef="transactionManagerSecondary",
        basePackages= { "net.zhaoxiaobin.jpa.dao.secondary" }) //设置Repository所在位置
public class SecondaryConfig {
    @Autowired
    private DataSource secondaryDataSource;

    @Autowired
    private JpaProperties jpaProperties;
    @Autowired
    private HibernateProperties hibernateProperties;

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

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

    @Bean(name = "entityManagerFactorySecondary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) {
        return builder.dataSource(secondaryDataSource)
                .packages("net.zhaoxiaobin.jpa.domain.secondary") //设置实体类所在位置
                .persistenceUnit("secondaryPersistenceUnit")
                .properties(getVendorProperties())
                .build();
    }

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

Repository配置:

public interface SecondaryRepository extends JpaRepository<User,Long> {

}

实体类配置:

@Entity
@Table(name = "user")
@Data
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name",length = 64)
    private String name;

    @Column(name = "age")
    private int age;
}

说明与注意

  • 在使用JPA的时候,需要为不同的数据源创建不同的package来存放对应的Entity和Repository,以便于配置类的分区扫描。
  • 类名上的注解@EnableJpaRepositories中指定Repository的所在位置。
  • LocalContainerEntityManagerFactoryBean创建的时候,指定Entity所在的位置。

2、测试

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class MultiDataSourceTest {
    @Autowired
    private PrimaryRepository primaryRepository;

    @Autowired
    private SecondaryRepository secondaryRepository;

    @Test
    public void testPrimary() {
        List<Actor> actorList = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            Actor actor = new Actor();
            actor.setActorName("actor" + i);
            actor.setActorEmail("email" + i);
            actor.setActorAge(i + 20);
            actorList.add(actor);
        }
        primaryRepository.saveAll(actorList);

        // 验证
//        Assert.assertEquals(5, primaryRepository.findAll().size());
    }

    @Test
    public void testSecondary() {
        List<User> userList = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            User user = new User();
            user.setName("userName" + i);
            user.setAge(i);
            userList.add(user);
        }
        secondaryRepository.saveAll(userList);

        // 验证
//        Assert.assertEquals(5, secondaryRepository.findAll().size());
    }
}

3、工程结构

├── jpa-multi-datasource.iml
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── net
    │   │       └── zhaoxiaobin
    │   │           └── jpa
    │   │               ├── JpaMultiDatasourceApplication.java
    │   │               ├── config
    │   │               │   ├── DataSourceConfig.java
    │   │               │   ├── PrimaryConfig.java
    │   │               │   └── SecondaryConfig.java
    │   │               ├── dao
    │   │               │   ├── primary
    │   │               │   │   └── PrimaryRepository.java
    │   │               │   └── secondary
    │   │               │       └── SecondaryRepository.java
    │   │               └── domain
    │   │                   ├── primary
    │   │                   │   └── Actor.java
    │   │                   └── secondary
    │   │                       └── User.java
    │   └── resources
    │       ├── application.yml
    │       └── hibernate.properties
    └── test
        └── java
            └── net
                └── zhaoxiaobin
                    └── jpa
                        └── MultiDataSourceTest.java

参考文章

代码地址

  • github:https://github.com/senlinmu1008/jpa-action/tree/master/jpa-multi-datasource
  • gitee:https://gitee.com/ppbin/jpa-action/tree/master/jpa-multi-datasource

个人网站

本文地址:https://blog.csdn.net/weixin_39020878/article/details/110008293

相关标签: JPA spring boot