Spring Data JPA中多数据源的配置

2023-08-23 17:33:42 浏览数 (2)

1、添加多数据源的配置

1.1、yaml配置
代码语言:javascript复制
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、数据源配置
代码语言:javascript复制
@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配置
代码语言:javascript复制
@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配置:

代码语言:javascript复制
public interface PrimaryRepository extends JpaRepository<Actor,Long> {

}

实体类配置:

代码语言:javascript复制
@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配置
代码语言:javascript复制
@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配置:

代码语言:javascript复制
public interface SecondaryRepository extends JpaRepository<User,Long> {

}

实体类配置:

代码语言:javascript复制
@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、测试

代码语言:javascript复制
@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、工程结构

代码语言:javascript复制
├── 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

参考链接

  • Spring Boot 2.x基础教程:Spring Data JPA的多数据源配置

代码地址

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

0 人点赞