用mybatis实现批量插入在使用sharingJdbc分库分表情况下遇到的问题

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");	

这就可以了

你可能感兴趣的:(mybatis及分库分表)