- pom依賴
<!-- spring data jpa依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 此示例使用mysql8版本 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
- spring boot 多數(shù)據(jù)源配置
#數(shù)據(jù)源配置 mysql8 使用com.mysql.cj.jdbc.Driver驅(qū)動扼褪,PS:serverTimezone=GMT需要加上,不然服務(wù)器時間不能同步
spring.datasource.test.driver-class-name=com.mysql.cj.jdbc.Driver
#新版本mysql竖席,必須帶上時區(qū)說明serverTimezone=GMT
#GMT會少了8小時旭咽,所以這里用GMT+8振惰,轉(zhuǎn)義后:GMT%2b8
spring.datasource.test.jdbc-url=jdbc\:mysql\://localhost\:3306/test?serverTimezone\=GMT%2b8&autoReconnect\=true&useUnicode\=true&characterEncoding\=UTF-8&useSSL\=true
spring.datasource.test.username=root
spring.datasource.test.password=
spring.datasource.test.max-idle=10
spring.datasource.test.max-wait=10000
spring.datasource.test.min-idle=5
spring.datasource.test.initial-size=5
#本地 訂單數(shù)據(jù)源配置
spring.datasource.order.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.order.jdbc-url=jdbc\:mysql\://localhost\:3306/order?serverTimezone\=GMT%2b8&autoReconnect\=true&useUnicode\=true&characterEncoding\=UTF-8&useSSL\=true
spring.datasource.order.username=root
spring.datasource.order.password=
spring.datasource.order.max-idle=10
spring.datasource.order.max-wait=10000
spring.datasource.order.min-idle=5
spring.datasource.order.initial-size=5
#1.251 業(yè)務(wù)數(shù)據(jù)源配置
spring.datasource.report.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.report.jdbc-url=jdbc\:mysql\://192.168.1.251\:3306/gnota?serverTimezone\=GMT%2b8&autoReconnect\=true&useUnicode\=true&characterEncoding\=UTF-8&useSSL\=true
spring.datasource.report.username=root
spring.datasource.report.password=
spring.datasource.report.max-idle=10
spring.datasource.report.max-wait=10000
spring.datasource.report.min-idle=5
spring.datasource.report.initial-size=5
- spring boot jpa 配置
#SQL輸出
spring.jpa.show-sql=true
#spring.jpa.properties.hibernate.hbm2ddl.auto說明
#create:Hibernate每次刪除上次生成内狸,然后根據(jù)實體重新生成表,哪怕實體沒有變化也照樣執(zhí)行关炼。
#create-drop:Hibernate每次根據(jù)實體生成表,sessionFactory關(guān)閉匣吊,表自動刪除儒拂。
#update:比較常用,先建好數(shù)據(jù)庫色鸳,Hibernate第一次根據(jù)實體自動建表社痛,后面根據(jù)實體說明結(jié)構(gòu)自動更新表結(jié)構(gòu),表一直存在命雀。PS:發(fā)布服務(wù)器后蒜哀,服務(wù)器啟動不會立馬執(zhí)行,得到app調(diào)用
#validate:Hibernate每次驗證創(chuàng)建數(shù)據(jù)庫表結(jié)構(gòu)吏砂,只會和數(shù)據(jù)庫中的表進比較撵儿,不會創(chuàng)建新表,但是會插入新值狐血。
spring.jpa.properties.hibernate.hbm2ddl.auto=update
#新版mysql方言MySQL5InnoDBDialect
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
#format SQL進?輸出
spring.jpa.properties.hibernate.format_sql=true
#jpa多數(shù)據(jù)源配置后調(diào)用autoware dao接口可能會報相同bean名沖突
#2種方法可以解決统倒,打開spring.main.allow-bean-definition-overriding或在springboot啟動類添加注解
#@ComponentScan(nameGenerator = AnnotationBeanNameGenerator.class)
#如果junit測試,在類頭部也要加上該注解
#這里用注解解決相同名bean沖突氛雪,所以注釋了allow-bean-definition-overriding
#相同bean名覆蓋注冊 SpringBoot 2.1之前,這個配置默認就是true耸成,而在2.1做了更改报亩。
#spring.main.allow-bean-definition-overriding=true
- 針對不同數(shù)據(jù)源配置生成對應(yīng)的DataSource的Configuration
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
/**
* 數(shù)據(jù)集源配置浴鸿,此示例配置了3個數(shù)據(jù)源<br>
*1,spring.datasource.test<br>
*2弦追,spring.datasource.order<br>
*3岳链,spring.datasource.report<br>
* 通過配置文件中的前綴,區(qū)分?jǐn)?shù)據(jù)源
* @author kyoxue
* @date 2019年10月28日
*/
@Configuration
public class DemoDBConfiguration {
/** 定義數(shù)據(jù)源 */
//默認數(shù)據(jù)源
@Primary
//bean名稱
@Bean(name="orderDB")
//為數(shù)據(jù)源取別名區(qū)分
@Qualifier("orderDB")
//指定配置數(shù)據(jù)源前綴
@ConfigurationProperties("spring.datasource.order")
public DataSource orderDB() {
return DataSourceBuilder.create().build();
}
//bean名稱
@Bean(name="reportDB")
//為數(shù)據(jù)源取別名區(qū)分
@Qualifier("reportDB")
//指定配置數(shù)據(jù)源前綴
@ConfigurationProperties("spring.datasource.report")
public DataSource reportDB() {
return DataSourceBuilder.create().build();
}
//bean名稱
@Bean(name="testDB")
//為數(shù)據(jù)源取別名區(qū)分
@Qualifier("testDB")
//指定配置數(shù)據(jù)源前綴
@ConfigurationProperties("spring.datasource.test")
public DataSource testDB() {
return DataSourceBuilder.create().build();
}
}
- 使用對應(yīng)的DataSource生成JPA對應(yīng)的配置
主要工作內(nèi)容:
1.通過DataSource的bean實例劲件,實體對象的包路徑來產(chǎn)生對應(yīng)該數(shù)據(jù)源的jpa環(huán)境
2.生成JPA的對應(yīng)api接口EntityManager
3.生成對應(yīng)數(shù)據(jù)源的事務(wù)PlatformTransactionManager
有一定注意:EntityManagerFactoryBuilder此處的包路徑為org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder
而非org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder
orderDB對應(yīng)的JPA配置
package com.example.demo;
import java.util.Map;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* 針對localhost:3306/order數(shù)據(jù)源的JPA配置
* ps:多數(shù)據(jù)源掸哑,JPA配置類至少有一個,其下所有方法添加primary注解
* 本示例primary寫在test數(shù)據(jù)源配置中
* @author kyoxue
* @date 2019年10月30日
*/
//標(biāo)識此為spring bean 配置類零远,啟動時加載
@Configuration
//啟用事務(wù)支持
@EnableTransactionManagement
@EnableJpaRepositories(
//JPA數(shù)據(jù)訪問環(huán)境
entityManagerFactoryRef="localContainerEntityManagerFactoryBeanOrder",
//JPA事務(wù)
transactionManagerRef="transactionManagerOrder",
//dao接口包掃描
basePackages={"com.example.demo.dao.order"})
public class DemoJPAOrderConfiguration {
//引入orderDB數(shù)據(jù)源苗分,別名orderDB與DemoDBConfiguration中@Qualifier("orderDB")一致
//注意:@Qualifier不可少,否則導(dǎo)致不能準(zhǔn)確區(qū)分?jǐn)?shù)據(jù)源
@Autowired
@Qualifier("orderDB")
private DataSource orderDB;
@Autowired
private JpaProperties jpaProperties;
@Resource
private HibernateProperties hibernateProperties;
private Map<String, Object> getVendorProperties() {
return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
}
/**
* 創(chuàng)建JPA數(shù)據(jù)訪問環(huán)境
* @param entityManagerFactoryBuilder
* @return
*/
@Bean(name="localContainerEntityManagerFactoryBeanOrder")
public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanOrder(org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder entityManagerFactoryBuilderOrder) {
return entityManagerFactoryBuilderOrder
//數(shù)據(jù)源
.dataSource(orderDB)
//JPA配置信息
.properties(getVendorProperties())
//實體類的包路徑
.packages("com.example.demo.entity.order")
//JPA數(shù)據(jù)環(huán)境名稱定義
.persistenceUnit("persistenceUnitOrder")
.build();
}
/**
* 操控數(shù)據(jù)庫的對應(yīng)API
* EntityManager是JPA中?于增牵辣、刪摔癣、改、查的接?
* 纬向,它的作?相當(dāng)于?座橋梁
* 择浊,連接內(nèi)存中的Java對象 和數(shù)據(jù)庫的數(shù)據(jù)存儲。
* 使?EntityManager中的相關(guān)接?對數(shù)據(jù)庫實體進?操作的時候
* 逾条,EntityManager會跟蹤實體對象的狀態(tài)
* 琢岩,并決定在特定時刻將對實體的操作映射到數(shù)據(jù)庫操作上?
* @param entityManagerFactoryBuilderOrder
* @return
*/
@Bean(name="entityManagerOrder")
public EntityManager entityManagerOrder(org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder entityManagerFactoryBuilderOrder){
return localContainerEntityManagerFactoryBeanOrder(entityManagerFactoryBuilderOrder).getObject().createEntityManager();
}
/**
* 給數(shù)據(jù)源添加JPA事務(wù)
* @param entityManagerFactoryBuilderOrder
* @return
*/
@Bean(name="transactionManagerOrder")
PlatformTransactionManager transactionManagerOrder(EntityManagerFactoryBuilder entityManagerFactoryBuilderOrder){
return new JpaTransactionManager(localContainerEntityManagerFactoryBeanOrder(entityManagerFactoryBuilderOrder).getObject());
}
}
reportDB對應(yīng)的JPA配置
package com.example.demo;
import java.util.Map;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* 針對192.168.1.251:3306/gnota數(shù)據(jù)源的JPA配置
* ps:多數(shù)據(jù)源,JPA配置類至少有一個师脂,其下所有方法添加primary注解
* 本示例primary寫在test數(shù)據(jù)源配置中
* @author kyoxue
* @date 2019年10月30日
*/
//標(biāo)識此為spring bean 配置類担孔,啟動時加載
@Configuration
//啟用事務(wù)支持
@EnableTransactionManagement
@EnableJpaRepositories(
//JPA數(shù)據(jù)訪問環(huán)境
entityManagerFactoryRef="localContainerEntityManagerFactoryBeanReport",
//JPA事務(wù)
transactionManagerRef="transactionManagerReport",
//dao接口包掃描
basePackages={"com.example.demo.dao.report"})
public class DemoJPAReportConfiguration {
//引入reportDB數(shù)據(jù)源,屬性名reportDB與DemoDBConfiguration中@Qualifier("reportDB")一致
@Autowired
@Qualifier("reportDB")
private DataSource reportDB;
@Autowired
private JpaProperties jpaProperties;
@Resource
private HibernateProperties hibernateProperties;
private Map<String, Object> getVendorProperties() {
return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
}
/**
* 創(chuàng)建JPA數(shù)據(jù)訪問環(huán)境
* @param entityManagerFactoryBuilder
* @return
*/
@Bean(name="localContainerEntityManagerFactoryBeanReport")
public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanReport(org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder entityManagerFactoryBuilderReport) {
return entityManagerFactoryBuilderReport
//數(shù)據(jù)源
.dataSource(reportDB)
//JPA配置信息
.properties(getVendorProperties())
//實體類的包路徑
.packages("com.example.demo.entity.report")
//JPA數(shù)據(jù)環(huán)境名稱定義
.persistenceUnit("persistenceUnitReport")
.build();
}
/**
* 操控數(shù)據(jù)庫的對應(yīng)API
* EntityManager是JPA中?于增危彩、刪攒磨、改、查的接?
* 汤徽,它的作?相當(dāng)于?座橋梁
* 娩缰,連接內(nèi)存中的Java對象 和數(shù)據(jù)庫的數(shù)據(jù)存儲。
* 使?EntityManager中的相關(guān)接?對數(shù)據(jù)庫實體進?操作的時候
* 谒府,EntityManager會跟蹤實體對象的狀態(tài)
* 拼坎,并決定在特定時刻將對實體的操作映射到數(shù)據(jù)庫操作上?
* @param entityManagerFactoryBuilderReport
* @return
*/
@Bean(name="entityManagerReport")
public EntityManager entityManagerReport(org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder entityManagerFactoryBuilderReport){
return localContainerEntityManagerFactoryBeanReport(entityManagerFactoryBuilderReport).getObject().createEntityManager();
}
/**
* 給數(shù)據(jù)源添加JPA事務(wù)
* @param entityManagerFactoryBuilderReport
* @return
*/
@Bean(name="transactionManagerReport")
PlatformTransactionManager transactionManagerReport(EntityManagerFactoryBuilder entityManagerFactoryBuilderReport){
return new JpaTransactionManager(localContainerEntityManagerFactoryBeanReport(entityManagerFactoryBuilderReport).getObject());
}
}
testDB對應(yīng)的JPA配置,注意一點:testDB這個JPA配置類每個bean方法都加了@Primary注解完疫,可以任意一個配置類加@Primary注解泰鸡,其余不用,但至少有一個配置類是這樣的
package com.example.demo;
import java.util.Map;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* 針對localhost:3306/test數(shù)據(jù)源的JPA配置
* ps:多數(shù)據(jù)源壳鹤,JPA配置類至少有一個盛龄,其下所有方法添加primary注解
* @author kyoxue
* @date 2019年10月30日
*/
//標(biāo)識此為spring bean 配置類,啟動時加載
@Configuration
//啟用事務(wù)支持
@EnableTransactionManagement
@EnableJpaRepositories(
//JPA數(shù)據(jù)訪問環(huán)境
entityManagerFactoryRef="localContainerEntityManagerFactoryBeanTest",
//JPA事務(wù)
transactionManagerRef="transactionManagerTest",
//dao接口包掃描
basePackages={"com.example.demo.dao.test"})
public class DemoJPATestConfiguration {
//引入testDB數(shù)據(jù)源,屬性名testDB與DemoDBConfiguration中@Qualifier("testDB")一致
@Autowired
@Qualifier("testDB")
private DataSource testDB;
@Autowired
private JpaProperties jpaProperties;
@Resource
private HibernateProperties hibernateProperties;
private Map<String, Object> getVendorProperties() {
return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
}
/**
* 創(chuàng)建JPA數(shù)據(jù)訪問環(huán)境
* @param entityManagerFactoryBuilder
* @return
*/
@Bean(name="localContainerEntityManagerFactoryBeanTest")
@Primary
public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanTest(org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder entityManagerFactoryBuilderTest) {
return entityManagerFactoryBuilderTest
//數(shù)據(jù)源
.dataSource(testDB)
//JPA配置信息
.properties(getVendorProperties())
//實體類的包路徑
.packages("com.example.demo.entity.test")
//JPA數(shù)據(jù)環(huán)境名稱定義
.persistenceUnit("persistenceUnitTest")
.build();
}
/**
* 操控數(shù)據(jù)庫的對應(yīng)API
* EntityManager是JPA中?于增余舶、刪啊鸭、改、查的接?
* 匿值,它的作?相當(dāng)于?座橋梁
* 赠制,連接內(nèi)存中的Java對象 和數(shù)據(jù)庫的數(shù)據(jù)存儲。
* 使?EntityManager中的相關(guān)接?對數(shù)據(jù)庫實體進?操作的時候
* 挟憔,EntityManager會跟蹤實體對象的狀態(tài)
* 钟些,并決定在特定時刻將對實體的操作映射到數(shù)據(jù)庫操作上?
* @param entityManagerFactoryBuilderTest
* @return
*/
@Bean(name="entityManagerTest")
@Primary
public EntityManager entityManagerTest(org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder entityManagerFactoryBuilderTest){
return localContainerEntityManagerFactoryBeanTest(entityManagerFactoryBuilderTest).getObject().createEntityManager();
}
/**
* 給數(shù)據(jù)源添加JPA事務(wù)
* @param entityManagerFactoryBuilderTest
* @return
*/
@Bean(name="transactionManagerTest")
@Primary
PlatformTransactionManager transactionManagerTest(EntityManagerFactoryBuilder entityManagerFactoryBuilderTest){
return new JpaTransactionManager(localContainerEntityManagerFactoryBeanTest(entityManagerFactoryBuilderTest).getObject());
}
}
- 對應(yīng)配置中包位置建立dao接口已經(jīng)實體類
-
testDB
-
orderDB
-
reportDB
- 對dao以及entity代碼如下
/**
* 繼承JpaRepository<實體名稱,實體主鍵類型>,使用其內(nèi)置大量常用API
* @author kyoxue
* @date 2019年10月31日
*/
@Qualifier("testJPA")
public interface TestJPADao extends JpaRepository<EntityTestJPA, Long> {
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity(name="jpa_test")
public class EntityTestJPA {
@Id
@GeneratedValue
private Long id;
@Column
private String testName;
//setter...getter...
}
@Qualifier("orderJPA")
public interface OrderJPADao extends JpaRepository<EntityOrder, Long> {
}
@Entity(name="jpa_order")
public class EntityOrder {
@Id
//主鍵生成策略GenerationType包括AUTO绊谭、INDENTITY政恍、SEQUENCE和TABLE
//generator主鍵生成器名稱
@GeneratedValue(strategy=GenerationType.AUTO,generator="order_generator")
private Long id;
@Column
private Date time;
@Column
private String orderNo;
//setter...getter...
}
@Qualifier("reportJPA")
public interface ReportJPADao extends JpaRepository<EntityReport, Integer> {
}
@Entity(name = "jpa_report")
public class EntityReport {
@Id
@GeneratedValue
private Integer id;
@Column
private String reportName;
//setter...getter...
}
- junit測試多數(shù)據(jù)源操作
@RunWith(SpringRunner.class)
//因為項目用到了websocket,這里引入隨機端口
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
//相同bean名沖突解決龙誊,springboot解決bean命名沖突可以加入這個注解抚垃,也可以在配置文件加入spring.main.allow-bean-definition-overriding=true
@ComponentScan(nameGenerator = AnnotationBeanNameGenerator.class)
public class applicationTest {
@Resource
private TestJPADao testJPA;
@Resource
private OrderJPADao orderJPA;
@Resource
private ReportJPADao reportJPA;
@Test
public void testEntityTestJPA()throws Exception{
EntityTestJPA vo = new EntityTestJPA();
vo.setTestName("ttt1");
testJPA.save(vo);
}
@Test
public void testEntityOrderJPA()throws Exception{
EntityOrder vo = new EntityOrder();
vo.setOrderNo("aaaa");
vo.setTime(new Date());
orderJPA.save(vo);
}
@Test
public void testEntityReportJPA()throws Exception{
EntityReport vo = new EntityReport();
vo.setReportName("tttttt");
reportJPA.save(vo);
}
}
- 查看數(shù)據(jù)庫是否正確操作
-
testDB
-
orderDB
-
reportDB
- 至此,多數(shù)據(jù)源測試完畢趟大。