本文是Spring Boot整合數據持久化方案的最後一篇,主要和大夥來聊聊Spring Boot整合Jpa多數據源問題。在Spring Boot整合JbdcTemplate多數據源、Spring Boot整合MyBatis多數據源以及Spring Boot整合Jpa多數據源這三個知識點中,整合Jpa多數據源算是最複雜的一種,也是不少人在配置時最容易出錯的一種。java
首先是建立一個Spring Boot工程,建立時添加基本的Web、Jpa以及MySQL依賴,以下:mysql
建立完成後,添加Druid依賴,這裏和前文的要求同樣,要使用專爲Spring Boot打造的Druid,大夥可能發現了,若是整合多數據源必定要使用這個依賴,由於這個依賴中才有DruidDataSourceBuilder。完整依賴以下:web
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
如此以後,工程就建立成功了。spring
在基本配置中,咱們首先來配置多數據源基本信息以及DataSource,首先在application.properties中添加以下配置信息:sql
spring.datasource.one.url=jdbc:mysql:///ssm?serverTimezone=UTC spring.datasource.one.username=xiaoliu spring.datasource.one.password=960614abcd spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.two.url=jdbc:mysql:///xiaoliu?serverTimezone=UTC spring.datasource.two.username=xiaoliu spring.datasource.two.password=960614abcd spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource spring.jpa.properties.hibernate.ddl-auto=update spring.jpa.properties.database-platform=mysql spring.jpa.properties.database=mysql spring.jpa.properties.show-sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
這裏Jpa的配置和上文相比key中多了properties,多數據源的配置和前文一致,而後接下來配置兩個DataSource,以下:app
@Configuration public class DataSourceConfig { @Bean @Primary @ConfigurationProperties(prefix = "spring.datasource.one") DataSource dsOne(){ return DruidDataSourceBuilder.create().build(); } @Bean @ConfigurationProperties(prefix = "spring.datasource.two") DataSource dsTwo(){ return DruidDataSourceBuilder.create().build(); } }
這裏的配置和前文的多數據源配置基本一致,可是注意多了一個在Spring中使用較少的註解@Primary,這個註解必定不能少,不然在項目啓動時會出錯,@Primary表示當某一個類存在多個實例時,優先使用哪一個實例。ide
好了,這樣,DataSource就有了。spring-boot
接下來配置Jpa的基本信息,這裏兩個數據源,我分別在兩個類中來配置,先來看第一個配置:測試
@Configuration @EnableJpaRepositories(basePackages = "cn.itxiaoliu.dao1",entityManagerFactoryRef ="localContainerEntityManagerFactoryBean1", transactionManagerRef = "platformTransactionManager1") public class JpaConfig1 { @Autowired @Qualifier("dsOne") DataSource dsOne; /** * */ @Autowired JpaProperties jpaProperties; @Bean @Primary LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean1(EntityManagerFactoryBuilder builder){ return builder.dataSource(dsOne) .properties(jpaProperties.getProperties()) .persistenceUnit("pu1") .packages("cn.itxiaoliu.bean") .build(); } @Bean PlatformTransactionManager platformTransactionManager1(EntityManagerFactoryBuilder builder){ return new JpaTransactionManager(localContainerEntityManagerFactoryBean1(builder).getObject()); } }
首先這裏注入dsOne,再注入JpaProperties,JpaProperties是系統提供的一個實例,裏邊的數據就是咱們在application.properties中配置的jpa相關的配置。而後咱們提供兩個Bean,分別是LocalContainerEntityManagerFactoryBean和PlatformTransactionManager事務管理器,不一樣於MyBatis和JdbcTemplate,在Jpa中,事務必定要配置。在提供LocalContainerEntityManagerFactoryBean的時候,須要指定packages,這裏的packages指定的包就是這個數據源對應的實體類所在的位置,另外在這裏配置類上經過@EnableJpaRepositories註解指定dao所在的位置,以及LocalContainerEntityManagerFactoryBean和PlatformTransactionManager分別對應的引用的名字。ui
好了,這樣第一個就配置好了,第二個基本和這個相似,主要有幾個不一樣點:
注意實體類能夠共用。
代碼以下:
@Configuration @EnableJpaRepositories(basePackages = "cn.itxiaoliu.dao2",entityManagerFactoryRef ="localContainerEntityManagerFactoryBean2", transactionManagerRef = "platformTransactionManager2") public class JpaConfig2 { @Autowired @Qualifier("dsTwo") DataSource dsTwo; /** * */ @Autowired JpaProperties jpaProperties; @Bean LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean2(EntityManagerFactoryBuilder builder){ return builder.dataSource(dsTwo) .properties(jpaProperties.getProperties()) .persistenceUnit("pu2") .packages("cn.itxiaoliu.bean") .build(); } @Bean PlatformTransactionManager platformTransactionManager2(EntityManagerFactoryBuilder builder){ return new JpaTransactionManager(localContainerEntityManagerFactoryBean2(builder).getObject()); } }
接下來,在對應位置分別提供相關的實體類和dao便可,數據源一的dao以下:
public interface BookDao1 extends JpaRepository<Book,Integer> { }
數據源二的dao以下:
public interface BookDao2 extends JpaRepository<Book,Integer> { }
共同的實體類以下:
@Entity(name = "t_book") public class Book { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; private String author; @Override public String toString() { return "Book{" + "id=" + id + ", name='" + name + '\'' + ", author='" + author + '\'' + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } }
到此,全部的配置就算完成了,接下來就能夠在Service中注入不一樣的UserDao,不一樣的UserDao操做不一樣的數據源。
其實整合Jpa多數據源也不算難,就是有幾個細節問題,這些細節問題解決,其實前面介紹的其餘多數據源整個都差很少。
接下來在測試類中進行測試
@RunWith(SpringRunner.class) @SpringBootTest public class Jpa2ApplicationTests { @Autowired BookDao1 bookDao1; @Autowired BookDao2 bookDao2; @Test public void contextLoads() { List<Book> all = bookDao1.findAll(); System.out.println(all); List<Book> all1 = bookDao2.findAll(); System.out.println(all1); } }