SpringBoot集成多數(shù)據(jù)源解析
一,前面我們介紹了springboot的快速啟動(dòng),大家肯定對(duì)springboot也有所了解,下面我們來(lái)介紹一下springboot怎么集成多數(shù)據(jù)源。
在有的項(xiàng)目開(kāi)發(fā)中需要在一個(gè)項(xiàng)目中訪問(wèn)多個(gè)數(shù)據(jù)源或者兩個(gè)項(xiàng)目之間通信(實(shí)質(zhì)上是互相訪問(wèn)對(duì)方的數(shù)據(jù)庫(kù)),在這里,我們介紹一下在一個(gè)項(xiàng)目中如何集成多個(gè)數(shù)據(jù)源(即訪問(wèn)多個(gè)不同的數(shù)據(jù)庫(kù)),因?yàn)樵陧?xiàng)目中有時(shí)會(huì)有這種需求,比如在一個(gè)大型項(xiàng)目開(kāi)發(fā)中,一個(gè)數(shù)據(jù)庫(kù)中保存數(shù)據(jù)的索引,各種使用頻繁的數(shù)據(jù),另一個(gè)數(shù)據(jù)庫(kù)中保存其他的數(shù)據(jù)。
1.下面我們來(lái)討論一個(gè)問(wèn)題,怎么集成多數(shù)據(jù)源,就是怎么讓一個(gè)項(xiàng)目訪問(wèn)多個(gè)數(shù)據(jù)庫(kù)?
有的人會(huì)說(shuō)使用注解,沒(méi)錯(cuò),這是一種辦法,因?yàn)閟pringboot對(duì)的最大好處就是避免了繁瑣的xml配置文件,大量的使用注解來(lái)開(kāi)發(fā),方便簡(jiǎn)潔,但是在這里如果集成多數(shù)據(jù)源使用注解的話會(huì)很麻煩,有沒(méi)有其他的辦法呢?答案是肯定的,我們可以分模板來(lái)訪問(wèn)多個(gè)數(shù)據(jù)庫(kù),也就是分包。
2.如何分包來(lái)訪問(wèn)多個(gè)數(shù)據(jù)源?
在這里,我們用一個(gè)簡(jiǎn)單的案例來(lái)說(shuō)明,我們?cè)L問(wèn)新建一個(gè)spingboot項(xiàng)目,訪問(wèn)test1,test2這兩個(gè)數(shù)據(jù)庫(kù),首先,我們先看代碼。
首先,我們需要導(dǎo)入相關(guān)依賴在pom文件中,這里,因?yàn)槲业捻?xiàng)目已經(jīng)提前有了父pom,所以不再考慮依賴的版本問(wèn)題,怎么建立父pom可參考上一篇文章。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>cn.shinelon.springboot</groupId> <artifactId>microboot</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>springboot-MultiDatasources</artifactId> <packaging>war</packaging> <!-- maven項(xiàng)目packaging改為war類(lèi)型時(shí),必須要加這個(gè)插件 --> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.3</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 測(cè)試springboot的依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- 測(cè)試時(shí)加入這兩個(gè)依賴,當(dāng)修改代碼的時(shí)候就不用每次修改后重啟服務(wù)器了 --> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <!-- springboot 集成jsp必須要借助這兩個(gè)依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> <!-- springboot集成mybatis --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> </dependencies> </project>
在上面配置的pom文件中,有點(diǎn)要說(shuō)明,因?yàn)橐L問(wèn)數(shù)據(jù)庫(kù),所以我整合了mybatis,還有一個(gè)是整合jsp,不過(guò)在這個(gè)項(xiàng)目中無(wú)關(guān),是我之前寫(xiě)代碼留下來(lái)的,可不必關(guān)心。
下面,我們還要在scr/main/sources目錄下新建一個(gè)application.properties資源文件,注意,這個(gè)文件名必須是application,這個(gè)是固定的,springboot默認(rèn)訪問(wèn)該文件,不要自己亂改名稱。然后在這個(gè)資源文件中配置自定義數(shù)據(jù)源。
spring.datasource.test1.driverClassName=com.mysql.jdbc.Driver spring.datasource.test1.url=jdbc:mysql://localhost:3306/test1 spring.datasource.test1.username=root spring.datasource.test1.password=..... spring.datasource.test2.driverClassName=com.mysql.jdbc.Driver spring.datasource.test2.url=jdbc:mysql://localhost:3306/test2 spring.datasource.test2.username=root spring.datasource.test2.password=.....
配置好數(shù)據(jù)源后我們就可以開(kāi)進(jìn)行分模塊來(lái)訪問(wèn)這兩個(gè)數(shù)據(jù)源了。首先在src/mian/java目錄下創(chuàng)建好各個(gè)包,然后開(kāi)始開(kāi)發(fā),新建一個(gè)datasource包來(lái)放置需要訪問(wèn)的兩個(gè)數(shù)據(jù)源的代碼,然后在新建兩個(gè)模塊包test1和test2,從包名我們就可以看出來(lái)這兩個(gè)包是用來(lái)操作這兩個(gè)數(shù)據(jù)庫(kù),在這兩個(gè)包下可以分別建立DAO層和service層的包,然后建立一個(gè)controller控制層。下面是項(xiàng)目的目錄樹(shù)圖。
然后我們來(lái)寫(xiě)DataSource中的代碼,其實(shí)就是像我們以前在xml文件中配置的SqlSessionFactory和數(shù)據(jù)源一個(gè)原理。
import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; @Configuration @MapperScan(basePackages="cn.shinelon.test1",sqlSessionFactoryRef="test1SqlSessionFactory") public class Datasource1 { /** * 配置test1數(shù)據(jù)庫(kù) * @return */ @Bean(name="test1Datasource") @ConfigurationProperties(prefix="spring.datasource.test1") public DataSource testDatasource() { return DataSourceBuilder.create().build(); } /** * 創(chuàng)建SqlSessionFactory * @param dataSource * @return * @throws Exception */ @Bean(name="test1SqlSessionFactory") public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1Datasource")DataSource dataSource) throws Exception { SqlSessionFactoryBean bean=new SqlSessionFactoryBean(); bean.setDataSource(dataSource); //如果還有分頁(yè)等其他事務(wù) // bean.setMapperLocations(new PathMatchingResourcePatternResolver(). // getResources("classpath:mybatis/test1/*.xml")); return bean.getObject(); } /** * 配置事務(wù)管理 * @param dataSource * @return */ @Bean(name="test1TransactionManager") public DataSourceTransactionManager testTransactionManager( @Qualifier("test1Datasource")DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean(name="test1SqlSessionTemplate") public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } }
上面的是訪問(wèn)的test1數(shù)據(jù)庫(kù)的配置,需要注意的是@ConfigurationProperties(prefix=”spring.datasource.test1”)這個(gè)配置中的屬性prefix的值必須和資源文件中的前綴是一樣的,否則是訪問(wèn)不到的,還有@Primary ,如果不加這個(gè)注解,啟動(dòng)將會(huì)報(bào)錯(cuò),因?yàn)榉?wù)器先要有一個(gè)默認(rèn)不知道默認(rèn)要先訪問(wèn)的數(shù)據(jù)源是哪個(gè),必須指明,下面是test2數(shù)據(jù)庫(kù)的配置,和上面一樣的。
import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; @Configuration @MapperScan(basePackages="cn.shinelon.test2",sqlSessionFactoryRef="test2SqlSessionFactory") @Primary //指定 默認(rèn)的訪問(wèn)的數(shù)據(jù)源 public class Datasource2 { /** * 配置test2數(shù)據(jù)庫(kù) * @return */ @Bean(name="test2Datasource") @ConfigurationProperties(prefix="spring.datasource.test2") @Primary //指定 默認(rèn)的訪問(wèn)的數(shù)據(jù)源 public DataSource testDatasource() { return DataSourceBuilder.create().build(); } /** * 創(chuàng)建SqlSessionFactory * @param dataSource * @return * @throws Exception */ @Bean(name="test2SqlSessionFactory") @Primary //指定 默認(rèn)的訪問(wèn)的數(shù)據(jù)源 public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2Datasource")DataSource dataSource) throws Exception { SqlSessionFactoryBean bean=new SqlSessionFactoryBean(); bean.setDataSource(dataSource); //如果還有分頁(yè)等其他事務(wù) // bean.setMapperLocations(new PathMatchingResourcePatternResolver(). // getResources("classpath:mybatis/test2/*.xml")); return bean.getObject(); } /** * 配置事務(wù)管理 * @param dataSource * @return */ @Bean(name="test2TransactionManager") @Primary //指定 默認(rèn)的訪問(wèn)的數(shù)據(jù)源 public DataSourceTransactionManager testTransactionManager( @Qualifier("test2Datasource")DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean(name="test2SqlSessionTemplate") public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } }
然后我們?cè)诿恳粋€(gè)模塊中寫(xiě)DAO層和service代碼來(lái)進(jìn)行操作。
DAO層代碼如下
public interface User1Dao { @Insert("insert into user values(null,#{username},#{age})") public void insert(@Param("username")String username,@Param("age")int age); }
在這里,我們向數(shù)據(jù)庫(kù)插入一條數(shù)據(jù)。
service層代碼如下
@Service public class User1Service { @Autowired public User1Dao user1Dao; public void insert(String username,int age) { user1Dao.insert(username, age); } }
test2包下DAO層和service層的代碼都是同樣的,這里就省略了。
然后我們來(lái)開(kāi)始寫(xiě)controller層的代碼。
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import cn.shinelon.test1.services.User1Service; import cn.shinelon.test2.services.User2Service; @SpringBootApplication @ComponentScan(basePackages={"cn.shinelon.datasource","cn.shinelon.test1","cn.shinelon.test2"}) @RestController public class UserController { @Autowired public User1Service user1Service; @Autowired public User2Service user2Service; @RequestMapping("/add") public String insert(String username,int age) { user1Service.insert(username, age); user2Service.insert(username, age); return "insert success"; } public static void main(String[] args) { SpringApplication.run(UserController.class, args); } }
上面代碼中 ,需要注意的是@ComponentScan(basePackages={“cn.shinelon.datasource”,”cn.shinelon.test1”,”cn.shinelon.test2”})這個(gè)注解,必須添加,這樣服務(wù)器才會(huì)掃描到這幾個(gè)包中的配置。
下面我們補(bǔ)全代碼,還要建立一個(gè)實(shí)體類(lèi)
public class User { private int id; private String username; private int age; //省略get,set方法 }
最后的整個(gè)項(xiàng)目圖如下
總結(jié)
以上就是本文關(guān)于SpringBoot集成多數(shù)據(jù)源解析的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:Maven管理SpringBoot Profile詳解、springboot掃描自定義的servlet和filter代碼詳解、淺談Springboot之于Spring的優(yōu)勢(shì)等,有什么問(wèn)題可以隨時(shí)留言,小編會(huì)及時(shí)回復(fù)大家的。感謝朋友們對(duì)本站的支持!
相關(guān)文章
使用java實(shí)現(xiàn)telnet-client工具分享
這篇文章主要介紹了使用java實(shí)現(xiàn)telnet-client工具,需要的朋友可以參考下2014-03-03Spring中Transactional注解使用的心得(推薦)
這篇文章主要介紹了Spring中Transactional注解使用的心得,事務(wù)是用來(lái)控制數(shù)據(jù)的ACID特性的,用于保證數(shù)據(jù)的正確性和完整性,需要的朋友可以參考下2022-10-10關(guān)于Java中XML Namespace 命名空間問(wèn)題
這篇文章主要介紹了Java中XML Namespace 命名空間,XML命名空間是由國(guó)際化資源標(biāo)識(shí)符 (IRI) 標(biāo)識(shí)的 XML 元素和屬性集合,該集合通常稱作 XML“詞匯”,對(duì)XML Namespace 命名空間相關(guān)知識(shí)感興趣的朋友一起看看吧2021-08-08實(shí)例詳解Java實(shí)現(xiàn)圖片與base64字符串之間的轉(zhuǎn)換
這篇文章主要介紹了Java實(shí)現(xiàn)圖片與base64字符串之間的轉(zhuǎn)換實(shí)例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2016-12-12Spring boot打包jar分離lib和resources方法實(shí)例
這篇文章主要介紹了Spring boot打包jar分離lib和resources方法實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05Java深入講解instanceof關(guān)鍵字的使用
instanceof 是 Java 的一個(gè)二元操作符,類(lèi)似于 ==,>,< 等操作符。instanceof 是 Java 的保留關(guān)鍵字。它的作用是測(cè)試它左邊的對(duì)象是否是它右邊的類(lèi)的實(shí)例,返回 boolean 的數(shù)據(jù)類(lèi)型2022-05-05Spring?AOP實(shí)現(xiàn)聲明式事務(wù)機(jī)制源碼解析
這篇文章主要為大家介紹了Spring?AOP實(shí)現(xiàn)聲明式事務(wù)機(jī)制源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12java數(shù)據(jù)結(jié)構(gòu)基礎(chǔ):棧
這篇文章主要介紹了Java的數(shù)據(jù)解構(gòu)基礎(chǔ),希望對(duì)廣大的程序愛(ài)好者有所幫助,同時(shí)祝大家有一個(gè)好成績(jī),需要的朋友可以參考下,希望能給你帶來(lái)幫助2021-07-07