要点
- 因为配置了双数据源,不用到spring自带的数据库连接,所以需要关闭资源的自动配置(没有关闭未必会出错,但关闭了肯定没有错):
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
//组件基包扫描,让spring boot管理其它模块bean类的生命周期
@ComponentScan("com")
public class Schedule {
public static void main(String[] args) {
SpringApplication.run(Schedule.class, args);
}
}
- 本文档记录多数据源配置中,测试发现无法通过 mapper.xml 进行接口的配置。
具体原因未发现,也未找到解决方式,所以对DB的操作是用的注解的方式。
实现
1 配置数据源信息
以下为其中一个数据源配置信息
spring.secondary.datasource.driverClassName = com.mysql.jdbc.Driver
spring.secondary.datasource.url = jdbc:mysql://10.10.14.56:3306/ppj?characterEncoding=UTF-8&rewriteBatchedStatements=true
spring.secondary.datasource.username = ppj.
spring.secondary.datasource.password = ppj.
2 数据库配置信息
以下为主库配置信息, @primary 为必填注解。
在有多个同类型的资源配置时,@primary 标注当前资源为默认配置。
空闲检测等配置,根据具体的业务需求。当前例子配置,是因为每天调用一次,不需要保持连接状态,空闲时将连接断开即可。
主库连接池配置如下:
package com.config;
import com.alibaba.druid.pool.DruidDataSource;
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.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
/**
* 配置主数据库源
* 有多候选者情况下,primary必写,不然会出现冲突;
* 采用primary消解的对象,默认采用
*
* @author pengpj
* @date 2018/7/23
*/
@Configuration
@MapperScan(basePackages = "com.mapper.alarm", sqlSessionTemplateRef = "primarySST")
public class PrimaryDataSourceConfig {
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.username}")
private String userName;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.driverClassName}")
private String driverClass;
@Primary
@Bean(name = "primaryDS")
public DataSource primaryDataSource() {
DruidDataSource dataSource = new DruidDataSource();
//基本连接信息
dataSource.setUrl(url);
dataSource.setUsername(userName);
dataSource.setPassword(password);
dataSource.setDriverClassName(driverClass);
//具体配置
dataSource.setInitialSize(1);
dataSource.setMinIdle(0);
dataSource.setMaxActive(1);
//空闲检测
dataSource.setTestWhileIdle(true);
//调用连接时检测是否可用
dataSource.setTestOnBorrow(true);
dataSource.setValidationQuery("select 1");
//获取连接的等待超时时间
dataSource.setMaxWait(1000 * 20L);
//检测需要关闭的空闲连接
dataSource.setTimeBetweenEvictionRunsMillis(1000 * 30L);
//连接池的最小生存时间
dataSource.setMinEvictableIdleTimeMillis(1000 * 30L);
return dataSource;
}
@Primary
@Bean(name = "primarySSF")
public SqlSessionFactory primarySqlSessionFactory(@Qualifier("primaryDS") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
}
@Primary
@Bean(name = "primaryTM")
public DataSourceTransactionManager primaryTransactionManager(@Qualifier("primaryDS") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Primary
@Bean(name = "primarySST")
public SqlSessionTemplate primarySqlSessionTemplate(@Qualifier("primarySSF") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
另一数据库配置连接池配置如上,删去 @primary 注解,并更改 Bean 中 name 值,name 不重复即可。
3 mapper 接口操作类
注意如下几点:
- 包名,与主库连接池配置的 @MapperScan 中 basePackages 属性相同,这样即可以用对应的连接池进行数据库操作。
- 注解用到了两个,@Mapper,@Repository,前者是 mabatis,后者是 spring 用于实例化。
以主库mapper为例:
package com.mapper.alarm;
import com.cvte.alarm.platform.user.copy.entity.AlarmUser;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;
/**
* 用户操作
*
* @author pengpj
* @date 2018/5/4
*/
@Mapper
@Repository
public interface AlarmUserMapper {
/**
* 插入数据
*
* @param entity user
* @return change row number
*/
@Insert("INSERT INTO" +
" alarm_user(user_name,user_login_name,email,pwd,user_type,auth_type,create_time,update_time,uid) " +
" VALUES(#{userName},#{userLoginName},#{email},#{pwd},#{userType},#{authType},#{createTime},#{updateTime},#{uid})")
Integer insert(AlarmUser entity);
/**
* 通过 userLoginName 查询用户信息
*
* @param userLoginName userLoginName
* @return user
*/
@Select("SELECT * FROM alarm_user WHERE user_login_name = #{userLoginName}")
@Results(
{
@Result(property = "uid",column = "uid"),
@Result(property = "userLoginName",column = "user_login_name")
}
)
AlarmUser findUserByUserLoginName(@Param("userLoginName") String userLoginName);
}
4 接口调用
Spring注入后,即可用接口进行数据库操作。
用例调用代码如下:
··· 省略
public void execute() {
List<ApmUser> apmUsers = apmUserMapper.obtainApmUserAfterTimestamp(timestamp);
}
private AlarmUserMapper alarmUserMapper;
@Autowired
public UserUpdateSchedule(AlarmUserMapper alarmUserMapper) {
this.alarmUserMapper = alarmUserMapper;
}