2019独角兽企业重金招聘Python工程师标准>>>
首先考虑使用缓存来处理,如果缓存不够用,再使用读写分离来实现
application.yml配置两个数据源
#默认使用配置
spring:
profiles:
active: dev
---
#开发配置
spring:
profiles: dev
datasource:
master:
jdbc-url: jdbc:mysql://localhost:3812/test
username: user
password: pwd
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
slave:
jdbc-url: jdbc:mysql://localhost:3812/test
username: user
password: pwd
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
Application.java 注意Mapper上加@Mapper注解,然后可以被扫描到
@SpringBootApplication
@EnableAutoConfiguration
@MapperScan("com.xx.mobile.group.dao")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
DataSourceConfig.java 注意有三个DataSource
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.slave")
public DataSource slave1DataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public DataSource myRoutingDataSource(@Qualifier("masterDataSource") DataSource masterDataSource,
@Qualifier("slave1DataSource") DataSource slave1DataSource) {
Map
DBType
public enum DBTypeEnum {
MASTER, SLAVE;
}
MybatisConfig 注意注入的DataSource,注意事务注解的order
@EnableTransactionManagement(order = 2)
@Configuration
public class MyBatisConfig {
@Resource(name = "myRoutingDataSource")
private DataSource myRoutingDataSource;
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(myRoutingDataSource);
sqlSessionFactoryBean.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
return sqlSessionFactoryBean.getObject();
}
@Bean
public PlatformTransactionManager platformTransactionManager() {
return new DataSourceTransactionManager(myRoutingDataSource);
}
}
DataSourceRouting
public class DataSourceRouting extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DBContextHolder.get();
}
}
DBContextHolder
public class DBContextHolder {
private static final ThreadLocal contextHolder = new ThreadLocal<>();
private static final AtomicInteger counter = new AtomicInteger(-1);
public static void set(DBTypeEnum dbType) {
contextHolder.set(dbType);
}
public static DBTypeEnum get() {
return contextHolder.get();
}
public static void master() {
set(DBTypeEnum.MASTER);
System.out.println("切换到master");
}
public static void slave() {
set(DBTypeEnum.SLAVE);
System.out.println("切换到slave");
}
}
使用从库注解UseSlaveDatabase
public @interface UseSlaveDatabase {
}
DataSourceAop 注意此切面的Order
@Aspect
@Component
public class DataSourceAop implements Ordered{
@Override
public int getOrder() {
return 0;
}
@Before("readPointcut()")
public void read() {
DBContextHolder.slave();
}
@Pointcut("@annotation(com.xx.mobile.config.UseSlaveDatabase)")
public void readPointcut() {
}
}
测试类
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class TestTask {
@Autowired
private ITaskService taskService;
@Test
public void save() throws Exception {
}
@Test
public void query() throws Exception {
//query方法可以用上面的注解
}
}
相关的service dao mapper entity没有写 原理:多个数据源汇集到一个数据源上(myRoutingDataSource),然后定义切面,遇到有UseSlaveDatabase注解就设置数据源为从库,默认使用主库,因为myRoutingDataSource.setDefaultTargetDataSource(masterDataSource);
注意数据源选择要在是事务之前,所以切面的order要注意。