个人博客
1、添加多数据源的配置
1.1、yaml配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| 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
|
注意:
- 这里为了方便,2个数据源的配置是用同一个数据库。
- 如果使用默认的数据源,在
SpringBoot2.x
以后需要使用jdbc-url
而非url
,否则会报 java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName.
。
1.2、数据源配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @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配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| @Configuration @EnableTransactionManagement @EnableJpaRepositories( entityManagerFactoryRef="entityManagerFactoryPrimary", transactionManagerRef="transactionManagerPrimary", basePackages= { "net.zhaoxiaobin.jpa.dao.primary" }) 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配置:
1 2 3
| public interface PrimaryRepository extends JpaRepository<Actor,Long> {
}
|
实体类配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Entity @Table(name = "actor") @Data public class Actor {
@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配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| @Configuration @EnableTransactionManagement @EnableJpaRepositories( entityManagerFactoryRef="entityManagerFactorySecondary", transactionManagerRef="transactionManagerSecondary", basePackages= { "net.zhaoxiaobin.jpa.dao.secondary" }) 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配置:
1 2 3
| public interface SecondaryRepository extends JpaRepository<User,Long> {
}
|
实体类配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @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、测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| @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);
}
@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);
} }
|
3、工程结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| ├── 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
|
参考链接
代码地址