最近項目有一個非解決不可的問題,咱們的項目中的用戶表是用的本身庫的數據,可是這些數據都是從一個已有庫中遷過來的,因此用戶信息都是在那個項目裏面維護,天然而然咱們項目不提供用戶註冊功能,這就有個問題,如何解決數據遷移的問題,總不能我每次都手動導數據吧,因此我決心寫一個接口把那個庫中的用戶信息同步咱們的庫中去。java
這又涉及到一個問題,如何在一個服務中鏈接兩個庫,在網上搜索了一番,算是把問題解決了,現將多數據源demo代碼貼出來,先看一下個人目錄結構mysql
controller、mapper、pojo、service這幾個常見的業務邏輯包咱們放到最後看,先看一下util包裏面的類spring
/** * 採用枚舉的方法列出全部的數據源key(經常使用數據庫名稱來命名) * 數據源個數和數據庫個數保持一致 */ public enum DatabaseType { mytestdb,mytestdb2 }
這裏就是列出全部的數據源,至關於定義了兩個常量,便於統一維護sql
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; /** * 動態數據源(須要繼承AbstractRoutingDataSource) */ public class DynamicDataSource extends AbstractRoutingDataSource { //定義一個線程安全的DatabaseType容器 private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<DatabaseType>(); public static DatabaseType getDatabaseType(){ return contextHolder.get(); } public static void setDatabaseType(DatabaseType type) { contextHolder.set(type); } //獲取當前線程的DatabaseType protected Object determineCurrentLookupKey() { return getDatabaseType(); } }
在這裏建立一個動態數據源的類,定義了DatabaseType的get和set方法,用getDatabaseType()得到一個當前線程的DatabaseType來重寫determineCurrentLookupKey()方法。數據庫
最後來看一下config包下面的類apache
import java.util.HashMap; import java.util.Map; import java.util.Properties; import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.EnvironmentAware; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.env.Environment; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import com.alibaba.druid.pool.DruidDataSourceFactory; import com.fiberhome.ms.multiDataSource.util.DatabaseType; import com.fiberhome.ms.multiDataSource.util.DynamicDataSource; /** * springboot集成mybatis的基本入口 * 1) 獲取數據源 * 2)建立數據源 * 3)建立SqlSessionFactory * 4)配置事務管理器,除非須要使用事務,不然不用配置 */ @Configuration public class MybatisConfig implements EnvironmentAware { private Environment environment; public void setEnvironment(final Environment environment) { this.environment = environment; } /** * 建立數據源,從配置文件中獲取數據源信息 */ @Bean public DataSource testDataSource() throws Exception { Properties props = new Properties(); props.put("driverClassName", environment.getProperty("jdbc.driverClassName")); props.put("url", environment.getProperty("jdbc.url")); props.put("username", environment.getProperty("jdbc.username")); props.put("password", environment.getProperty("jdbc.password")); return DruidDataSourceFactory.createDataSource(props); } @Bean public DataSource test1DataSource() throws Exception { Properties props = new Properties(); props.put("driverClassName", environment.getProperty("jdbc2.driverClassName")); props.put("url", environment.getProperty("jdbc2.url")); props.put("username", environment.getProperty("jdbc2.username")); props.put("password", environment.getProperty("jdbc2.password")); return DruidDataSourceFactory.createDataSource(props); } /**注入數據源 */ @Bean public DynamicDataSource dataSource(@Qualifier("testDataSource")DataSource testDataSource, @Qualifier("test1DataSource")DataSource test1DataSource) { Map<Object, Object> targetDataSources = new HashMap<Object, Object>(); targetDataSources.put(DatabaseType.mytestdb, testDataSource); targetDataSources.put(DatabaseType.mytestdb2, test1DataSource); DynamicDataSource dataSource = new DynamicDataSource(); dataSource.setTargetDataSources(targetDataSources);// 該方法是AbstractRoutingDataSource的方法 dataSource.setDefaultTargetDataSource(testDataSource);// 默認的datasource設置爲myTestDbDataSource return dataSource; } /** * 根據數據源建立SqlSessionFactory */ @Bean public SqlSessionFactory sqlSessionFactory(@Qualifier("testDataSource") DataSource testDataSource, @Qualifier("test1DataSource") DataSource test1DataSource) throws Exception{ PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); SqlSessionFactoryBean fb = new SqlSessionFactoryBean(); fb.setDataSource(this.dataSource(testDataSource, test1DataSource)); fb.setTypeAliasesPackage("com.fiberhome.ms.multiDataSource");// 指定基包 fb.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));// return fb.getObject(); } /** * 配置事務管理器 */ @Bean public DataSourceTransactionManager testTransactionManager(DynamicDataSource dataSource) throws Exception { return new DataSourceTransactionManager(dataSource); } }
上面這段代碼在建立數據源DataSource實例時採用的是@bean註解注入的方式,使其成爲受spring管理的bean。在後面的方法把兩個DataSource做爲參數傳入,能夠看到用了@Qualifier註解,加這個註解是爲了解決多個實例沒法直接裝配的問題,在這裏有兩個DataSource類型的實例,須要指定名稱裝配。安全
還有數據源配置文件springboot
#the first datasource jdbc.driverClassName = com.mysql.jdbc.Driver jdbc.url = jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8 jdbc.username = root jdbc.password = 123456 #the second datasource jdbc2.driverClassName = com.mysql.jdbc.Driver jdbc2.url = jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=UTF-8 jdbc2.username = root jdbc2.password = 123456
說完了關鍵的通用代碼,再來看看如何在業務代碼中使用session
import com.fiberhome.ms.multiDataSource.mapper.UserMapper; import com.fiberhome.ms.multiDataSource.pojo.User; import com.fiberhome.ms.multiDataSource.service.UserService; import com.fiberhome.ms.multiDataSource.util.DatabaseType; import com.fiberhome.ms.multiDataSource.util.DynamicDataSource; @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public List<User> getTestUser() { //設置數據源 DynamicDataSource.setDatabaseType(DatabaseType.mytestdb); return userMapper.findUser(); } @Override public List<User> getTest1User() { //設置數據源 DynamicDataSource.setDatabaseType(DatabaseType.mytestdb2); return userMapper.findUser(); } }
在service層的實現類中設置數據源便可指定哪一個mapper接口使用哪一個數據源,這樣就OK了。剩下的業務代碼很簡單就不貼了。。。mybatis