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
注意:
- 这里为了方便,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 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 {
}
实体类配置:
@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 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 {
}
实体类配置:
@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 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 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
参考链接
- 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