Spring Boot+Jpa多數(shù)據(jù)源配置的完整步驟
關(guān)于
有時(shí)候,隨著業(yè)務(wù)的發(fā)展,項(xiàng)目關(guān)聯(lián)的數(shù)據(jù)來(lái)源會(huì)變得越來(lái)越復(fù)雜,使用的數(shù)據(jù)庫(kù)會(huì)比較分散,這個(gè)時(shí)候就會(huì)采用多數(shù)據(jù)源的方式來(lái)獲取數(shù)據(jù)。另外,多數(shù)據(jù)源也有其他好處,例如分布式數(shù)據(jù)庫(kù)的讀寫(xiě)分離,集成多種數(shù)據(jù)庫(kù)等等。
下面分享我在實(shí)際項(xiàng)目中配置多數(shù)據(jù)源的案例。話不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧
步驟
1.application.yml文件中,配置數(shù)據(jù)庫(kù)源。這里primary是主庫(kù),secondary是從庫(kù)。
server: port: 8089 # 多數(shù)據(jù)源配置 #primary spring: primary: datasource: url: jdbc:mysql://127.0.0.1:3306/database1?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai username: root password: ****** driver-class-name: com.mysql.jdbc.Driver #secondary secondary: datasource: url: jdbc:mysql://127.0.0.1:3306/database1?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai username: root password: ****** driver-class-name: com.mysql.jdbc.Driver jpa: hibernate: primary-dialect: org.hibernate.dialect.MySQL5Dialect secondary-dialect: org.hibernate.dialect.MySQL5Dialect open-in-view: true show-sql: true
2.創(chuàng)建一個(gè)Spring配置類,其中spring.primary.datasource的路徑參考yml文件的配置。
@Configuration
public class DataSourceConfig {
@Bean(name = "primaryDataSource")
@Qualifier("primaryDataSource")
@ConfigurationProperties(prefix="spring.primary.datasource")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryDataSource")
@Qualifier("secondaryDataSource")
@Primary
@ConfigurationProperties(prefix="spring.secondary.datasource")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
3.分別創(chuàng)建主庫(kù)、從庫(kù)的配置類。
注意:entity包和dao包的配置,以及@Primary注解指定主庫(kù)。
主庫(kù)配置類:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerFactoryPrimary",
transactionManagerRef = "transactionManagerPrimary",
basePackages = {"com.infinitus.yunxiao_data.dao.primary"}) //設(shè)置Repository所在位置
public class PrimaryConfig {
@Autowired
private JpaProperties jpaProperties;
@Autowired
@Qualifier("primaryDataSource")
private DataSource primaryDataSource;
@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)
.properties(getVendorProperties(primaryDataSource))
.packages("com.infinitus.yunxiao_data.entity.primary") //設(shè)置實(shí)體類所在位置
.persistenceUnit("primaryPersistenceUnit")
.build();
}
private Map getVendorProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
}
@Primary
@Bean(name = "transactionManagerPrimary")
public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
}
}
從庫(kù)的配置類:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerFactorySecondary",
transactionManagerRef = "transactionManagerSecondary",
basePackages = {"com.infinitus.yunxiao_data.dao.secondary"}) //設(shè)置Repository所在位置
public class SecondaryConfig {
@Autowired
private JpaProperties jpaProperties;
@Autowired
@Qualifier("secondaryDataSource")
private DataSource secondaryDataSource;
@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)
.properties(getVendorProperties(secondaryDataSource))
.packages("com.infinitus.yunxiao_data.entity.secondary") //設(shè)置實(shí)體類所在位置
.persistenceUnit("primaryPersistenceUnit")
.build();
}
private Map getVendorProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
}
@Bean(name = "transactionManagerSecondary")
PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
}
}
4.分別創(chuàng)建主、從庫(kù)dao類。
主dao:
@Repository
public interface PrimaryRepository extends JpaRepository<PrimaryEntity, Long> {
@Query(value = "SELECT p FROM PrimaryEntity p")
List<PrimaryEntity> queryList();
}
從dao:
@Repository
public interface SecondaryRepository extends JpaRepository<SecondaryEntity, Long> {
@Query(value = "SELECT p FROM SecondaryEntity p")
List<SecondaryEntity> queryList();
}
5.分別創(chuàng)建主、從庫(kù)entity類。
主entity:
@Entity
@Table(name = "holiday_scheme")
@EntityListeners(AuditingEntityListener.class)
public class PrimaryEntity extends AbstractPersistable<Long> {
@Column(name = "date")
public String date;
@Column(name = "hour")
public String hour;
@Column(name = "holiday")
public String holiday;
@Column(name = "holiday_explain")
public String holiday_explain;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getHour() {
return hour;
}
public void setHour(String hour) {
this.hour = hour;
}
public String getHoliday() {
return holiday;
}
public void setHoliday(String holiday) {
this.holiday = holiday;
}
public String getHoliday_explain() {
return holiday_explain;
}
public void setHoliday_explain(String holiday_explain) {
this.holiday_explain = holiday_explain;
}
@Override
public String toString() {
return "PrimaryEntity{" +
"date='" + date + '\'' +
", hour='" + hour + '\'' +
", holiday='" + holiday + '\'' +
", holiday_explain='" + holiday_explain + '\'' +
'}';
}
}
從entity:
@Entity
@Table(name = "active_dashboards")
@EntityListeners(AuditingEntityListener.class)
public class SecondaryEntity extends AbstractPersistable<Long> {
@Column(name = "dashboard_id")
public String dashboard_id;
@Column(name = "user_id")
public String user_id;
@Column(name = "order_index")
public String order_index;
public String getDashboard_id() {
return dashboard_id;
}
public void setDashboard_id(String dashboard_id) {
this.dashboard_id = dashboard_id;
}
public String getUser_id() {
return user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
public String getOrder_index() {
return order_index;
}
public void setOrder_index(String order_index) {
this.order_index = order_index;
}
@Override
public String toString() {
return "SecondaryEntity{" +
"dashboard_id='" + dashboard_id + '\'' +
", user_id='" + user_id + '\'' +
", order_index='" + order_index + '\'' +
'}';
}
}
6.controller請(qǐng)求獲取不同數(shù)據(jù)庫(kù)的數(shù)據(jù)。
@RestController
@RequestMapping("/database")
public class MailController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
PrimaryRepository primaryRepository;
@Autowired
SecondaryRepository secondaryRepository;
@RequestMapping("/primary")
@ResponseBody
public String primary() {
return primaryRepository.queryList().toString();
}
@RequestMapping("/secondary")
@ResponseBody
public String secondary() {
return secondaryRepository.queryList().toString();
}
}
注意
下面提兩個(gè)在配置多數(shù)據(jù)源時(shí)遇到的坑點(diǎn),一不注意就掉坑了。
1.Application類不需要配置@EnableJpaRepositories注解,會(huì)報(bào)如下錯(cuò)誤。
A component required a bean named 'entityManagerFactory' that could not be f
2.注意檢查dao類,獲取數(shù)據(jù)的方法上格式是否正確,有沒(méi)有某個(gè)字段是表中不存在的,避免啟動(dòng)異常。如下,SecondaryEntity表中是不存在job_name字段的,所以注釋掉才能啟動(dòng)成功等。
//@Query(value = "SELECT p FROM SecondaryEntity p where p.job_name = ?1") //List<SecondaryEntity> queryOdcRecord(String job_name);
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
淺談springioc實(shí)例化bean的三個(gè)方法
下面小編就為大家?guī)?lái)一篇淺談springioc實(shí)例化bean的三個(gè)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就想給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09
基數(shù)排序簡(jiǎn)介及Java語(yǔ)言實(shí)現(xiàn)
這篇文章主要介紹了基數(shù)排序簡(jiǎn)介及Java語(yǔ)言實(shí)現(xiàn),涉及基數(shù)排序的基本思想簡(jiǎn)單介紹和桶排序的分析,以及基數(shù)排序的Java實(shí)現(xiàn),具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-11-11
idea構(gòu)建web項(xiàng)目的超級(jí)詳細(xì)教程
好多朋友在使用IDEA創(chuàng)建項(xiàng)目時(shí),總會(huì)碰到一些小問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于idea構(gòu)建web項(xiàng)目的超級(jí)詳細(xì)教程,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-03-03
Jmeter關(guān)聯(lián)實(shí)現(xiàn)及參數(shù)化使用解析
這篇文章主要介紹了Jmeter關(guān)聯(lián)實(shí)現(xiàn)及參數(shù)化使用解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
spring AOP的After增強(qiáng)實(shí)現(xiàn)方法實(shí)例分析
這篇文章主要介紹了spring AOP的After增強(qiáng)實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了spring面向切面AOP的After增強(qiáng)實(shí)現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下2020-01-01
Java基礎(chǔ)高級(jí)綜合練習(xí)題撲克牌的創(chuàng)建
今天小編就為大家分享一篇關(guān)于Java基礎(chǔ)高級(jí)綜合練習(xí)題撲克牌的創(chuàng)建,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-01-01
如何利用java控制鼠標(biāo)操作一些重復(fù)的事情
這篇文章主要給大家介紹了關(guān)于如何利用java控制鼠標(biāo)操作一些重復(fù)的事情,主要利用的是Robot類,Robot可以模擬鼠標(biāo)和鍵盤(pán)的輸入,相當(dāng)于Java版的按鍵精靈,需要的朋友可以參考下2021-12-12
SpringBoot + Spring Security 基本使用及個(gè)性化登錄配置詳解
這篇文章主要介紹了SpringBoot + Spring Security 基本使用及個(gè)性化登錄配置詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-05-05

