分库分表:解决思路,Dao-->ORM--->JDBC-->Proxy-->Server
1分库
在Dao层进行选择数据库
package org.springframework.jdbc.datasource.lookup下的
AbstractRoutingDataSource实现多数据源切换
package com.example.demo.multdatasource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* 多数据源切面
*/
@Aspect
@Slf4j
@Component
public class DataSourceAspect {
@Pointcut("@annotation( com.example.demo.multdatasource.TargetDataSource)")
public void pointcut() {
}
@Around("pointcut()")
public Object Around(ProceedingJoinPoint proceedingJoinPoint) {
MethodSignature methodSignature = (MethodSignature)proceedingJoinPoint.getSignature();
Method method = methodSignature.getMethod();
TargetDataSource annotation = method.getAnnotation(TargetDataSource.class);
if(annotation==null){
//目标方法上没有注解,设置默认为第一个数据源
MyAbstractDataSource.setDtaSource(DataSourceNames.FIRST);
}else{
//目标方法伤有数据源,就设置数据源为注解里的数据源
MyAbstractDataSource.setDtaSource(annotation.name());
}
try {
return proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}finally {
MyAbstractDataSource.clearDataSource();
}
return null;
}
}
package com.example.demo.multdatasource;
/**
* 多数据源选择设置处,也可以设置枚举
*/
public interface DataSourceNames {
String FIRST = "FIRST";
String SECOND = "SECOND";
}
package com.example.demo.multdatasource;
/**
* 演示Dao层注解获取
*/
public class MultDatraSourceDao {
@TargetDataSource(name = DataSourceNames.SECOND)
public Object getObject(){
return null;
}
}
package com.example.demo.multdatasource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.Map;
/**
* 多数据源切换实现
*/
public class MyAbstractDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> CONTEXT_HOLDER=new ThreadLocal<>();
/**
* 需要使用哪个数据源的信息以及默认数据源先配置好
* @param defaultTargetDataSource
* @param targetDataSources
*/
public MyAbstractDataSource(DataSource defaultTargetDataSource, Map<Object,Object> targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return getDataSource();
}
public static String getDataSource(){
return CONTEXT_HOLDER.get();
}
public static void setDtaSource(String dataSource){
CONTEXT_HOLDER.set(dataSource);
}
public static void clearDataSource(){
CONTEXT_HOLDER.remove();
}
}
package com.example.demo.multdatasource;
import java.lang.annotation.*;
/**
* 数据源注解处
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface TargetDataSource {
String name() default "";
}
package com.example.demo.multdatasource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* 多数据源配置处
*/
@Configuration
public class DynamicDataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.druid.first")
public DataSource firstDataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.druid.second")
public DataSource secondDataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean
@Primary
public MyAbstractDataSource dataSource(DataSource firstDataSource,DataSource secondDataSource){
Map<Object,Object> targetDataSource=new HashMap<>();
targetDataSource.put(DataSourceNames.FIRST,firstDataSource);
targetDataSource.put(DataSourceNames.SECOND,secondDataSource);
return new MyAbstractDataSource(firstDataSource,targetDataSource);
}
}