序文
実際のビジネスシナリオは、単にライブラリーすることはできませんので、サブライブラリーのサブテーブルがあり、より多くのデータソースがあります。別の読み取りを実現して書き込むには、主要なライブラリは、ライブラリから担当のクエリを削除するには追加や変更を担当しています。この記事では、どのように春ブーツマルチソースデータ、動的データソースの切り替え、個別の読み取りおよび書き込み操作を実現します。
コードの展開
クイック新規プロジェクト春ブートプロジェクト
1、Mavenの依存性を追加
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
図2に示すように、アプリケーションは、設定を読み取るために複数のデータソースを設定します
前とチュートリアル、最初のconfigure application.yml
#指定配置文件为test
spring:
profiles:
active: test
#配置Mybatis
mybatis:
configuration:
# 开启驼峰命名转换,如:Table(create_time) -> Entity(createTime)。不需要我们关心怎么进行字段匹配,mybatis会自动识别`大写字母与下划线`
map-underscore-to-camel-case: true
#打印SQL日志
logging:
level:
com.niaobulashi.mapper.*: DEBUG
ここで、この印刷ログSQL、理由は*で示される複数のデータソースには、次の区別異なるパケットマッパーソースデータベースのxmlファイル、。
アプリケーションtest.ymlとして配置
spring:
datasource:
#主库
master:
jdbc-url: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
#从库
slave:
jdbc-url: jdbc:mysql://127.0.0.1:3306/test2?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
ライブラリスレーブから、メインライブラリのマスターを区別する、spring.datasourceノードを起動します。本試験は、ライブラリTEST2からデータベース接続に接続されたデータベースリポジトリ。
注意:春BOOT2、複数のデータソースを構成するときに変更され、いくつかの設定から始め、多くのオンラインチュートリアルを使用して、ことに留意すべきですspring.datasource.url
。ありますjdbcUrl is required with driverClassName.
問題。
解決策:複数のデータソースを設定し、spring.datasource.url
設定にspring.datasource.jdbc-url
3、メインライブラリの設定情報を追加
基づいて、よく知られたブロガー:純粋な笑顔、私たちは波を分析する必要がブログ記事を書きます
まず、メインのライブラリ構成のコードを見て:
@Configuration
@MapperScan(basePackages = "com.niaobulashi.mapper.master", sqlSessionTemplateRef = "masterSqlSessionTemplate")
public class DataSourceMasterConfig {
/**
* 是application-test.yml中的spring.datasource.master配置生效
* @return
*/
@Bean(name = "masterDataSource")
@ConfigurationProperties(prefix = "spring.datasource.master")
@Primary
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
/**
* 将配置信息注入到SqlSessionFactoryBean中
* @param dataSource 数据库连接信息
* @return
* @throws Exception
*/
@Bean(name = "masterSqlSessionFactory")
@Primary
public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/master/*.xml"));
return bean.getObject();
}
/**
* 事务管理器,在实例化时注入主库master
* @param dataSource
* @return
*/
@Bean(name = "masterTransactionManager")
@Primary
public DataSourceTransactionManager masterTransactionManager(@Qualifier("masterDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/**
* SqlSessionTemplate具有线程安全性
* @param sqlSessionFactory
* @return
* @throws Exception
*/
@Bean(name = "masterSqlSessionTemplate")
@Primary
public SqlSessionTemplate masterSqlSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
問題はこれを見masterSqlSessionFactory
、SqlSessionFactoryBean
ちょうど取得spring.datasource.master
データベース接続情報を、そしてより多くの構成情報データベース得られなかったmybatis.configuration
私たちが命名こぶ、コンフィギュレーション情報を設定する必要があり、中に注入されていない原因をSqlSessionFactoryBean
。これは遭遇解決できないクエリになり、適切なフィールドがDEPT_ID、CREATE_TIME、USER_IDアンダースコア
ソリューション:コンフィギュレーションに設定を追加します。
一方、構成情報はSqlSessionFactoryBeanに注入されます
/**
* 将配置信息注入到SqlSessionFactoryBean中
* @param dataSource 数据库连接信息
* @return
* @throws Exception
*/
@Bean(name = "slaveSqlSessionFactory")
public SqlSessionFactory slaveSqlSessionFactory(@Qualifier("slaveDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
// 使配置信息加载到类中,再注入到SqlSessionFactoryBean
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
bean.setConfiguration(configuration);
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/slave/*.xml"));
return bean.getObject();
}
4、ライブラリから設定情報を追加
和添加主库配置信息一样,只不过不同的是,不需要添加@Primary
首选注解
代码如下
@Configuration
@MapperScan(basePackages = "com.niaobulashi.mapper.slave", sqlSessionTemplateRef = "slaveSqlSessionTemplate")
public class DataSourceSlaveConfig {
/**
* 是application-test.yml中的spring.datasource.master配置生效
* @return
*/
@Bean(name = "slaveDataSource")
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
/**
* 将配置信息注入到SqlSessionFactoryBean中
* @param dataSource 数据库连接信息
* @return
* @throws Exception
*/
@Bean(name = "slaveSqlSessionFactory")
public SqlSessionFactory slaveSqlSessionFactory(@Qualifier("slaveDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
// 使配置信息加载到类中,再注入到SqlSessionFactoryBean
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
bean.setConfiguration(configuration);
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/slave/*.xml"));
return bean.getObject();
}
/**
* 事务管理器,在实例化时注入主库master
* @param dataSource
* @return
*/
@Bean(name = "slaveTransactionManager")
public DataSourceTransactionManager slaveTransactionManager(@Qualifier("slaveDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/**
* SqlSessionTemplate具有线程安全性
* @param sqlSessionFactory
* @return
* @throws Exception
*/
@Bean(name = "slaveSqlSessionTemplate")
public SqlSessionTemplate slaveSqlSessionTemplate(@Qualifier("slaveSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
5、扩展配置方法会报错
在网上还看到这样一种配置,单独通过@ConfigurationProperties注解配置Mybatis的配置信息如下
/**
* 试application.yml中的mybatis.configuration配置生效,如果不主动配置,由于@Order配置顺序不同,讲导致配置不能及时生效
* 使配置信息加载到类中,再注入到SqlSessionFactoryBean
* @return
*/
@Bean
@ConfigurationProperties(prefix = "mybatis.configuration")
public org.apache.ibatis.session.Configuration configuration() {
return new org.apache.ibatis.session.Configuration();
}
其中prefix
,在主库和从库中的id是一样的,必须保持不同,否则idea就会提示报错Duplicate prefix
导致只有主库可以执行Mybatis的配置,从库无效。
@Bean(name = "masterSqlSessionFactory")
@Primary
public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource, org.apache.ibatis.session.Configuration configuration) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
// 使配置信息加载到类中,再注入到SqlSessionFactoryBean
bean.setConfiguration(configuration);
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/master/*.xml"));
return bean.getObject();
}
这块验证只有主库有效,从库的驼峰方法解析无效。后续再来研究下。。。
6、数据层代码
代码结构如下
其中SysUserMasterDao代码
public interface SysUserMasterDao {
/**
* 根据userId查询用户信息
* @param userId 用户ID
*/
List<SysUserEntity> queryUserInfo(Long userId);
/**
* 查询所有用户信息
*/
List<SysUserEntity> queryUserAll();
/**
* 根据userId更新用户的邮箱和手机号
* @return
*/
int updateUserInfo(SysUserEntity user);
}
7、resource下数据执行语句
SysCodeMasterDao.xml
<mapper namespace="com.niaobulashi.mapper.master.SysUserMasterDao">
<!--查询所有用户信息-->
<select id="queryUserAll" resultType="com.niaobulashi.entity.SysUserEntity">
SELECT
ur.*
FROM
sys_user ur
WHERE
1 = 1
</select>
<!--根据用户userId查询用户信息-->
<select id="queryUserInfo" resultType="com.niaobulashi.entity.SysUserEntity">
SELECT
ur.*
FROM
sys_user ur
WHERE
1 = 1
AND ur.user_id = #{userId}
</select>
<!-- 根据UserId,更新邮箱和手机号 -->
<update id="updateUserInfo" parameterType="com.niaobulashi.entity.SysUserEntity">
UPDATE sys_user u
<set>
<if test="email != null">
u.email = #{email},
</if>
<if test="mobile != null">
u.mobile = #{mobile},
</if>
</set>
WHERE
u.user_id = #{userId}
</update>
</mapper>
8、Controller层测试
@RestController
public class SysUserController {
@Autowired
private SysUserMasterDao sysUserMasterDao;
@Autowired
private SysUserSlaveDao sysUserSlaveDao;
/**
* 查询所有用户信息Master
* @return
*/
@RequestMapping("/getUserMasterAll")
private List<SysUserEntity> getUserMaster() {
System.out.println("查询主库");
List<SysUserEntity> userList = sysUserMasterDao.queryUserAll();
return userList;
}
/**
* 查询所有用户信息Slave
* @return
*/
@RequestMapping("/getUserSlaveAll")
private List<SysUserEntity> getUserSlave() {
System.out.println("查询从库");
List<SysUserEntity> userList = sysUserSlaveDao.queryUserAll();
return userList;
}
/**
* 根据userId查询用户信息Master
* @return
*/
@RequestMapping("/getUserMasterById")
private List<SysUserEntity> getUserMasterById(@RequestParam(value = "userId", required = false) Long userId) {
List<SysUserEntity> userList = sysUserMasterDao.queryUserInfo(userId);
return userList;
}
/**
* 根据userId查询用户信息Slave
* @return
*/
@RequestMapping("/getUserSlaveById")
private List<SysUserEntity> getUserSlaveById(@RequestParam(value = "userId", required = false) Long userId) {
List<SysUserEntity> userList = sysUserSlaveDao.queryUserInfo(userId);
return userList;
}
}
发送查询所有用户接口
主库:http://localhost:8080/getUserMasterAll
从库:http://localhost:8080/getUserSlaveAll
总结
1、通过多数据源方式实现数据库层面的读写分离
2、多数据源链接数据库是,使用spring.datasource.jdbc-url
3、多数据源的mybatis.configuration配置注意需要手动注入SqlSessionFactory