为什么80%的码农都做不了架构师?>>>
要点
- 因为配置了双数据源,不用到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;@Autowiredpublic UserUpdateSchedule(AlarmUserMapper alarmUserMapper) {this.alarmUserMapper = alarmUserMapper;}