You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

README.md 18 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. # spring-boot-demo-multi-datasource-jpa
  2. > 此 demo 主要演示 Spring Boot 如何集成 JPA 的多数据源。
  3. ## pom.xml
  4. ```xml
  5. <?xml version="1.0" encoding="UTF-8"?>
  6. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  7. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  8. <modelVersion>4.0.0</modelVersion>
  9. <artifactId>spring-boot-demo-multi-datasource-jpa</artifactId>
  10. <version>1.0.0-SNAPSHOT</version>
  11. <packaging>jar</packaging>
  12. <name>spring-boot-demo-multi-datasource-jpa</name>
  13. <description>Demo project for Spring Boot</description>
  14. <parent>
  15. <groupId>com.xkcoding</groupId>
  16. <artifactId>spring-boot-demo</artifactId>
  17. <version>1.0.0-SNAPSHOT</version>
  18. </parent>
  19. <properties>
  20. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  21. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  22. <java.version>1.8</java.version>
  23. </properties>
  24. <dependencies>
  25. <dependency>
  26. <groupId>org.springframework.boot</groupId>
  27. <artifactId>spring-boot-starter</artifactId>
  28. </dependency>
  29. <dependency>
  30. <groupId>org.springframework.boot</groupId>
  31. <artifactId>spring-boot-starter-test</artifactId>
  32. <scope>test</scope>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.springframework.boot</groupId>
  36. <artifactId>spring-boot-starter-data-jpa</artifactId>
  37. </dependency>
  38. <dependency>
  39. <groupId>mysql</groupId>
  40. <artifactId>mysql-connector-java</artifactId>
  41. </dependency>
  42. <dependency>
  43. <groupId>cn.hutool</groupId>
  44. <artifactId>hutool-all</artifactId>
  45. </dependency>
  46. <dependency>
  47. <groupId>com.google.guava</groupId>
  48. <artifactId>guava</artifactId>
  49. </dependency>
  50. <dependency>
  51. <groupId>org.projectlombok</groupId>
  52. <artifactId>lombok</artifactId>
  53. <optional>true</optional>
  54. </dependency>
  55. </dependencies>
  56. <build>
  57. <finalName>spring-boot-demo-multi-datasource-jpa</finalName>
  58. <plugins>
  59. <plugin>
  60. <groupId>org.springframework.boot</groupId>
  61. <artifactId>spring-boot-maven-plugin</artifactId>
  62. </plugin>
  63. </plugins>
  64. </build>
  65. </project>
  66. ```
  67. ## PrimaryDataSourceConfig.java
  68. > 主数据源配置
  69. ```java
  70. /**
  71. * <p>
  72. * JPA多数据源配置 - 主数据源
  73. * </p>
  74. *
  75. * @package: com.xkcoding.multi.datasource.jpa.config
  76. * @description: JPA多数据源配置 - 主数据源
  77. * @author: yangkai.shen
  78. * @date: Created in 2019-01-17 15:58
  79. * @copyright: Copyright (c) 2019
  80. * @version: V1.0
  81. * @modified: yangkai.shen
  82. */
  83. @Configuration
  84. public class PrimaryDataSourceConfig {
  85. /**
  86. * 扫描spring.datasource.primary开头的配置信息
  87. *
  88. * @return 数据源配置信息
  89. */
  90. @Primary
  91. @Bean(name = "primaryDataSourceProperties")
  92. @ConfigurationProperties(prefix = "spring.datasource.primary")
  93. public DataSourceProperties dataSourceProperties() {
  94. return new DataSourceProperties();
  95. }
  96. /**
  97. * 获取主库数据源对象
  98. *
  99. * @param dataSourceProperties 注入名为primaryDataSourceProperties的bean
  100. * @return 数据源对象
  101. */
  102. @Primary
  103. @Bean(name = "primaryDataSource")
  104. public DataSource dataSource(@Qualifier("primaryDataSourceProperties") DataSourceProperties dataSourceProperties) {
  105. return dataSourceProperties.initializeDataSourceBuilder().build();
  106. }
  107. /**
  108. * 该方法仅在需要使用JdbcTemplate对象时选用
  109. *
  110. * @param dataSource 注入名为primaryDataSource的bean
  111. * @return 数据源JdbcTemplate对象
  112. */
  113. @Primary
  114. @Bean(name = "primaryJdbcTemplate")
  115. public JdbcTemplate jdbcTemplate(@Qualifier("primaryDataSource") DataSource dataSource) {
  116. return new JdbcTemplate(dataSource);
  117. }
  118. }
  119. ```
  120. ## SecondDataSourceConfig.java
  121. > 从数据源配置
  122. ```java
  123. /**
  124. * <p>
  125. * JPA多数据源配置 - 次数据源
  126. * </p>
  127. *
  128. * @package: com.xkcoding.multi.datasource.jpa.config
  129. * @description: JPA多数据源配置 - 次数据源
  130. * @author: yangkai.shen
  131. * @date: Created in 2019-01-17 15:58
  132. * @copyright: Copyright (c) 2019
  133. * @version: V1.0
  134. * @modified: yangkai.shen
  135. */
  136. @Configuration
  137. public class SecondDataSourceConfig {
  138. /**
  139. * 扫描spring.datasource.second开头的配置信息
  140. *
  141. * @return 数据源配置信息
  142. */
  143. @Bean(name = "secondDataSourceProperties")
  144. @ConfigurationProperties(prefix = "spring.datasource.second")
  145. public DataSourceProperties dataSourceProperties() {
  146. return new DataSourceProperties();
  147. }
  148. /**
  149. * 获取主库数据源对象
  150. *
  151. * @param dataSourceProperties 注入名为secondDataSourceProperties的bean
  152. * @return 数据源对象
  153. */
  154. @Bean(name = "secondDataSource")
  155. public DataSource dataSource(@Qualifier("secondDataSourceProperties") DataSourceProperties dataSourceProperties) {
  156. return dataSourceProperties.initializeDataSourceBuilder().build();
  157. }
  158. /**
  159. * 该方法仅在需要使用JdbcTemplate对象时选用
  160. *
  161. * @param dataSource 注入名为secondDataSource的bean
  162. * @return 数据源JdbcTemplate对象
  163. */
  164. @Bean(name = "secondJdbcTemplate")
  165. public JdbcTemplate jdbcTemplate(@Qualifier("secondDataSource") DataSource dataSource) {
  166. return new JdbcTemplate(dataSource);
  167. }
  168. }
  169. ```
  170. ## PrimaryJpaConfig.java
  171. > 主 JPA 配置
  172. ```java
  173. /**
  174. * <p>
  175. * JPA多数据源配置 - 主 JPA 配置
  176. * </p>
  177. *
  178. * @package: com.xkcoding.multi.datasource.jpa.config
  179. * @description: JPA多数据源配置 - 主 JPA 配置
  180. * @author: yangkai.shen
  181. * @date: Created in 2019-01-17 16:54
  182. * @copyright: Copyright (c) 2019
  183. * @version: V1.0
  184. * @modified: yangkai.shen
  185. */
  186. @Configuration
  187. @EnableTransactionManagement
  188. @EnableJpaRepositories(
  189. // repository包名
  190. basePackages = PrimaryJpaConfig.REPOSITORY_PACKAGE,
  191. // 实体管理bean名称
  192. entityManagerFactoryRef = "primaryEntityManagerFactory",
  193. // 事务管理bean名称
  194. transactionManagerRef = "primaryTransactionManager")
  195. public class PrimaryJpaConfig {
  196. static final String REPOSITORY_PACKAGE = "com.xkcoding.multi.datasource.jpa.repository.primary";
  197. private static final String ENTITY_PACKAGE = "com.xkcoding.multi.datasource.jpa.entity.primary";
  198. /**
  199. * 扫描spring.jpa.primary开头的配置信息
  200. *
  201. * @return jpa配置信息
  202. */
  203. @Primary
  204. @Bean(name = "primaryJpaProperties")
  205. @ConfigurationProperties(prefix = "spring.jpa.primary")
  206. public JpaProperties jpaProperties() {
  207. return new JpaProperties();
  208. }
  209. /**
  210. * 获取主库实体管理工厂对象
  211. *
  212. * @param primaryDataSource 注入名为primaryDataSource的数据源
  213. * @param jpaProperties 注入名为primaryJpaProperties的jpa配置信息
  214. * @param builder 注入EntityManagerFactoryBuilder
  215. * @return 实体管理工厂对象
  216. */
  217. @Primary
  218. @Bean(name = "primaryEntityManagerFactory")
  219. public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("primaryDataSource") DataSource primaryDataSource, @Qualifier("primaryJpaProperties") JpaProperties jpaProperties, EntityManagerFactoryBuilder builder) {
  220. return builder
  221. // 设置数据源
  222. .dataSource(primaryDataSource)
  223. // 设置jpa配置
  224. .properties(jpaProperties.getProperties())
  225. // 设置实体包名
  226. .packages(ENTITY_PACKAGE)
  227. // 设置持久化单元名,用于@PersistenceContext注解获取EntityManager时指定数据源
  228. .persistenceUnit("primaryPersistenceUnit").build();
  229. }
  230. /**
  231. * 获取实体管理对象
  232. *
  233. * @param factory 注入名为primaryEntityManagerFactory的bean
  234. * @return 实体管理对象
  235. */
  236. @Primary
  237. @Bean(name = "primaryEntityManager")
  238. public EntityManager entityManager(@Qualifier("primaryEntityManagerFactory") EntityManagerFactory factory) {
  239. return factory.createEntityManager();
  240. }
  241. /**
  242. * 获取主库事务管理对象
  243. *
  244. * @param factory 注入名为primaryEntityManagerFactory的bean
  245. * @return 事务管理对象
  246. */
  247. @Primary
  248. @Bean(name = "primaryTransactionManager")
  249. public PlatformTransactionManager transactionManager(@Qualifier("primaryEntityManagerFactory") EntityManagerFactory factory) {
  250. return new JpaTransactionManager(factory);
  251. }
  252. }
  253. ```
  254. ## SecondJpaConfig.java
  255. > 从 JPA 配置
  256. ```java
  257. /**
  258. * <p>
  259. * JPA多数据源配置 - 次 JPA 配置
  260. * </p>
  261. *
  262. * @package: com.xkcoding.multi.datasource.jpa.config
  263. * @description: JPA多数据源配置 - 次 JPA 配置
  264. * @author: yangkai.shen
  265. * @date: Created in 2019-01-17 16:54
  266. * @copyright: Copyright (c) 2019
  267. * @version: V1.0
  268. * @modified: yangkai.shen
  269. */
  270. @Configuration
  271. @EnableTransactionManagement
  272. @EnableJpaRepositories(
  273. // repository包名
  274. basePackages = SecondJpaConfig.REPOSITORY_PACKAGE,
  275. // 实体管理bean名称
  276. entityManagerFactoryRef = "secondEntityManagerFactory",
  277. // 事务管理bean名称
  278. transactionManagerRef = "secondTransactionManager")
  279. public class SecondJpaConfig {
  280. static final String REPOSITORY_PACKAGE = "com.xkcoding.multi.datasource.jpa.repository.second";
  281. private static final String ENTITY_PACKAGE = "com.xkcoding.multi.datasource.jpa.entity.second";
  282. /**
  283. * 扫描spring.jpa.second开头的配置信息
  284. *
  285. * @return jpa配置信息
  286. */
  287. @Bean(name = "secondJpaProperties")
  288. @ConfigurationProperties(prefix = "spring.jpa.second")
  289. public JpaProperties jpaProperties() {
  290. return new JpaProperties();
  291. }
  292. /**
  293. * 获取主库实体管理工厂对象
  294. *
  295. * @param secondDataSource 注入名为secondDataSource的数据源
  296. * @param jpaProperties 注入名为secondJpaProperties的jpa配置信息
  297. * @param builder 注入EntityManagerFactoryBuilder
  298. * @return 实体管理工厂对象
  299. */
  300. @Bean(name = "secondEntityManagerFactory")
  301. public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("secondDataSource") DataSource secondDataSource, @Qualifier("secondJpaProperties") JpaProperties jpaProperties, EntityManagerFactoryBuilder builder) {
  302. return builder
  303. // 设置数据源
  304. .dataSource(secondDataSource)
  305. // 设置jpa配置
  306. .properties(jpaProperties.getProperties())
  307. // 设置实体包名
  308. .packages(ENTITY_PACKAGE)
  309. // 设置持久化单元名,用于@PersistenceContext注解获取EntityManager时指定数据源
  310. .persistenceUnit("secondPersistenceUnit").build();
  311. }
  312. /**
  313. * 获取实体管理对象
  314. *
  315. * @param factory 注入名为secondEntityManagerFactory的bean
  316. * @return 实体管理对象
  317. */
  318. @Bean(name = "secondEntityManager")
  319. public EntityManager entityManager(@Qualifier("secondEntityManagerFactory") EntityManagerFactory factory) {
  320. return factory.createEntityManager();
  321. }
  322. /**
  323. * 获取主库事务管理对象
  324. *
  325. * @param factory 注入名为secondEntityManagerFactory的bean
  326. * @return 事务管理对象
  327. */
  328. @Bean(name = "secondTransactionManager")
  329. public PlatformTransactionManager transactionManager(@Qualifier("secondEntityManagerFactory") EntityManagerFactory factory) {
  330. return new JpaTransactionManager(factory);
  331. }
  332. }
  333. ```
  334. ## application.yml
  335. ```yaml
  336. spring:
  337. datasource:
  338. primary:
  339. url: jdbc:mysql://127.0.0.1:3306/spring-boot-demo?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
  340. username: root
  341. password: root
  342. driver-class-name: com.mysql.cj.jdbc.Driver
  343. type: com.zaxxer.hikari.HikariDataSource
  344. hikari:
  345. minimum-idle: 5
  346. connection-test-query: SELECT 1 FROM DUAL
  347. maximum-pool-size: 20
  348. auto-commit: true
  349. idle-timeout: 30000
  350. pool-name: PrimaryHikariCP
  351. max-lifetime: 60000
  352. connection-timeout: 30000
  353. second:
  354. url: jdbc:mysql://127.0.0.1:3306/spring-boot-demo-2?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
  355. username: root
  356. password: root
  357. driver-class-name: com.mysql.cj.jdbc.Driver
  358. type: com.zaxxer.hikari.HikariDataSource
  359. hikari:
  360. minimum-idle: 5
  361. connection-test-query: SELECT 1 FROM DUAL
  362. maximum-pool-size: 20
  363. auto-commit: true
  364. idle-timeout: 30000
  365. pool-name: SecondHikariCP
  366. max-lifetime: 60000
  367. connection-timeout: 30000
  368. jpa:
  369. primary:
  370. show-sql: true
  371. generate-ddl: true
  372. hibernate:
  373. ddl-auto: update
  374. properties:
  375. hibernate:
  376. dialect: org.hibernate.dialect.MySQL57InnoDBDialect
  377. open-in-view: true
  378. second:
  379. show-sql: true
  380. generate-ddl: true
  381. hibernate:
  382. ddl-auto: update
  383. properties:
  384. hibernate:
  385. dialect: org.hibernate.dialect.MySQL57InnoDBDialect
  386. open-in-view: true
  387. logging:
  388. level:
  389. com.xkcoding: debug
  390. org.hibernate.SQL: debug
  391. org.hibernate.type: trace
  392. ```
  393. ## SpringBootDemoMultiDatasourceJpaApplicationTests.java
  394. ```java
  395. package com.xkcoding.multi.datasource.jpa;
  396. import cn.hutool.core.bean.BeanUtil;
  397. import cn.hutool.core.lang.Snowflake;
  398. import com.xkcoding.multi.datasource.jpa.entity.primary.PrimaryMultiTable;
  399. import com.xkcoding.multi.datasource.jpa.entity.second.SecondMultiTable;
  400. import com.xkcoding.multi.datasource.jpa.repository.primary.PrimaryMultiTableRepository;
  401. import com.xkcoding.multi.datasource.jpa.repository.second.SecondMultiTableRepository;
  402. import lombok.extern.slf4j.Slf4j;
  403. import org.junit.Test;
  404. import org.junit.runner.RunWith;
  405. import org.springframework.beans.factory.annotation.Autowired;
  406. import org.springframework.boot.test.context.SpringBootTest;
  407. import org.springframework.test.context.junit4.SpringRunner;
  408. import java.util.List;
  409. @RunWith(SpringRunner.class)
  410. @SpringBootTest
  411. @Slf4j
  412. public class SpringBootDemoMultiDatasourceJpaApplicationTests {
  413. @Autowired
  414. private PrimaryMultiTableRepository primaryRepo;
  415. @Autowired
  416. private SecondMultiTableRepository secondRepo;
  417. @Autowired
  418. private Snowflake snowflake;
  419. @Test
  420. public void testInsert() {
  421. PrimaryMultiTable primary = new PrimaryMultiTable(snowflake.nextId(),"测试名称-1");
  422. primaryRepo.save(primary);
  423. SecondMultiTable second = new SecondMultiTable();
  424. BeanUtil.copyProperties(primary, second);
  425. secondRepo.save(second);
  426. }
  427. @Test
  428. public void testUpdate() {
  429. primaryRepo.findAll().forEach(primary -> {
  430. primary.setName("修改后的"+primary.getName());
  431. primaryRepo.save(primary);
  432. SecondMultiTable second = new SecondMultiTable();
  433. BeanUtil.copyProperties(primary, second);
  434. secondRepo.save(second);
  435. });
  436. }
  437. @Test
  438. public void testDelete() {
  439. primaryRepo.deleteAll();
  440. secondRepo.deleteAll();
  441. }
  442. @Test
  443. public void testSelect() {
  444. List<PrimaryMultiTable> primary = primaryRepo.findAll();
  445. log.info("【primary】= {}", primary);
  446. List<SecondMultiTable> second = secondRepo.findAll();
  447. log.info("【second】= {}", second);
  448. }
  449. }
  450. ```
  451. ## 目录结构
  452. ```
  453. .
  454. ├── README.md
  455. ├── pom.xml
  456. ├── spring-boot-demo-multi-datasource-jpa.iml
  457. ├── src
  458. │   ├── main
  459. │   │   ├── java
  460. │   │   │   └── com.xkcoding.multi.datasource.jpa
  461. │   │   │   ├── SpringBootDemoMultiDatasourceJpaApplication.java
  462. │   │   │   ├── config
  463. │   │   │   │   ├── PrimaryDataSourceConfig.java
  464. │   │   │   │   ├── PrimaryJpaConfig.java
  465. │   │   │   │   ├── SecondDataSourceConfig.java
  466. │   │   │   │   ├── SecondJpaConfig.java
  467. │   │   │   │   └── SnowflakeConfig.java
  468. │   │   │   ├── entity
  469. │   │   │   │   ├── primary
  470. │   │   │   │   │   └── PrimaryMultiTable.java
  471. │   │   │   │   └── second
  472. │   │   │   │   └── SecondMultiTable.java
  473. │   │   │   └── repository
  474. │   │   │   ├── primary
  475. │   │   │   │   └── PrimaryMultiTableRepository.java
  476. │   │   │   └── second
  477. │   │   │   └── SecondMultiTableRepository.java
  478. │   │   └── resources
  479. │   │   └── application.yml
  480. │   └── test
  481. │   └── java
  482. │   └── com.xkcoding.multi.datasource.jpa
  483. │   └── SpringBootDemoMultiDatasourceJpaApplicationTests.java
  484. └── target
  485. ```
  486. ## 参考
  487. 1. https://www.jianshu.com/p/34730e595a8c
  488. 2. https://blog.csdn.net/anxpp/article/details/52274120

一个用来深度学习并实战 spring boot 的项目,目前总共包含 66 个集成demo,已经完成 55 个。