service层代码:
@Override
public void testBatchInsert() {
List datas = new ArrayList<>();
for (int i = 1; i < 5; i++) {
Long videoId = Long.parseLong(i + "");
VideoAuditProcess videoAuditProcess = new VideoAuditProcess();
videoAuditProcess.setVideoId(videoId);
videoAuditProcess.setAuditTranscationId(BaseUtils.createVideoAuditTranscationId());
// 机审综合结果(-1:未检测,0:正常,1:初级敏感,2:中级敏感,3:严格敏感)
videoAuditProcess.setmAuditResult(-1);
// 流程状态(0:未开始,1:进行中,2:已完成)
videoAuditProcess.setProcessStatus(0);
// 流程类型(1:机审自动,2:自动抽检)
videoAuditProcess.setProcessType(2);
videoAuditProcess.setCreateTimestamp(new Date().getTime());
datas.add(videoAuditProcess);
}
// CustomerContextHolder.setCustomerType("dataSource_normal");
videoAuditProcessMapperExt.batchInsert(datas);
}
mapper代码:
insert into video_audit_process (video_id, audit_transcation_id,
process_type, m_audit_result, process_status,
create_timestamp)
values
( #{videoAudit.videoId,jdbcType=BIGINT},
#{videoAudit.auditTranscationId,jdbcType=VARCHAR},
#{videoAudit.processType,jdbcType=INTEGER},
#{videoAudit.mAuditResult,jdbcType=INTEGER},
#{videoAudit.processStatus,jdbcType=INTEGER},
#{videoAudit.createTimestamp,jdbcType=BIGINT})
此时运行会报错:
### Cause: io.shardingjdbc.core.exception.ShardingJdbcException: Invoke jdbc method exception
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:23) ~[mybatis-3.2.4.jar:3.2.4]
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:150) ~[mybatis-3.2.4.jar:3.2.4]
at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:137) ~[mybatis-3.2.4.jar:3.2.4]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_231]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_231]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_231]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_231]
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:358) ~[mybatis-spring-1.2.2.jar:1.2.2]
... 106 more
说明此时sharingJdbc报错了,所以sharingJdbc这个插件不支持批量插入。因为我们代码配置的数据源默认使用的是sharingJdbc数据源。这从我们的配置可以看出:
false
然后使用aop进行数据源的选择:
import java.util.Map;
import org.aspectj.lang.JoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 动态切换数据源切面
*/
public class DataSourceAspect{
private static final Logger logger = LoggerFactory.getLogger(DataSourceAspect.class);
private String defaultDataSource;
private Map targetDataSources;
private String dataSourceBi;
public void doBefore(JoinPoint joinPoint) {
String className = joinPoint.getSignature().getDeclaringType().getSimpleName();
// logger.info("DataSourceAspect.className={}",className);
if ("WechatStatService".equals(className)) {
CustomerContextHolder.setCustomerType(dataSourceBi);
// logger.info("----------------------------------------------------------------className={}--------------------------------------------------------------dataSourceBi={}",className,dataSourceBi);
return;
}
boolean isSetDataSource = false;
String targetMethodName = joinPoint.getSignature().getName();
for(Map.Entry entry : targetDataSources.entrySet()) {
if(targetMethodName.contains(entry.getKey())){
String value = entry.getValue().toString();
CustomerContextHolder.setCustomerType(value);
isSetDataSource = true;
// logger.info("走不分表的数据源--");
break;
}
}
if(!isSetDataSource) {
CustomerContextHolder.setCustomerType(defaultDataSource);
}
}
public void doAfterReturning(JoinPoint joinPoint) {
CustomerContextHolder.clearCustomerType();
}
public Map getTargetDataSources() {
return targetDataSources;
}
public void setTargetDataSources(Map targetDataSources) {
this.targetDataSources = targetDataSources;
}
public String getDefaultDataSource() {
return defaultDataSource;
}
public void setDefaultDataSource(String defaultDataSource) {
this.defaultDataSource = defaultDataSource;
}
public String getDataSourceBi() {
return dataSourceBi;
}
public void setDataSourceBi(String dataSourceBi) {
this.dataSourceBi = dataSourceBi;
}
}
使用CustomerContextHolder保存当前线程使用的数据源:
public class CustomerContextHolder {
//用ThreadLocal来设置当前线程使用哪个dataSource
private static final ThreadLocal contextHolder = new ThreadLocal();
public static void setCustomerType(String customerType) {
contextHolder.set(customerType);
}
public static String getCustomerType() {
return contextHolder.get();
}
public static void clearCustomerType() {
contextHolder.remove();
}
}
然后使用spring的AbstractRoutingDataSource动态注入数据源:
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* 动态分派数据源
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return CustomerContextHolder.getCustomerType();
}
}
此时动态注入数据源就实现完成,回到最开始的问题:这个问题在于sharingJDBC不支持批量插入,所以应该切换普通数据源:
CustomerContextHolder.setCustomerType("dataSource_normal");
这就可以了