瀏覽代碼

导入数据优化

wangliang 3 年之前
父節點
當前提交
6c8a118ef4

+ 44 - 0
themis-business/src/main/java/com/qmth/themis/business/base/CustomBaseMapper.java

@@ -0,0 +1,44 @@
+package com.qmth.themis.business.base;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+/**
+ * @Description: 自定义mapper
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/5/11
+ */
+public interface CustomBaseMapper<T> extends BaseMapper<T> {
+
+    /**
+     * 自定义批量插入
+     * 如果要自动填充,@Param(xx) xx参数名必须是 list/collection/array 3个的其中之一
+     *
+     * @param list
+     * @return
+     */
+    int insertBatch(@Param("collection") Collection<? extends Serializable> list);
+
+    /**
+     * 自定义批量更新
+     * 如果要自动填充,@Param(xx) xx参数名必须是 list/collection/array 3个的其中之一
+     *
+     * @param list
+     * @return
+     */
+    int updateBatch(@Param("collection") Collection<? extends Serializable> list);
+
+    /**
+     * 自定义批量新增或更新
+     * 如果要自动填充,@Param(xx) xx参数名必须是 list/collection/array 3个的其中之一
+     *
+     * @param list
+     * @return
+     */
+    int insertOrUpdateBath(@Param("collection") Collection<? extends Serializable> list);
+}

+ 29 - 0
themis-business/src/main/java/com/qmth/themis/business/base/CustomizedSqlInjector.java

@@ -0,0 +1,29 @@
+package com.qmth.themis.business.base;
+
+import com.baomidou.mybatisplus.core.injector.AbstractMethod;
+import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
+
+import java.util.List;
+
+/**
+ * @Description: 自定义批量sql插入、更新
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/5/11
+ */
+public class CustomizedSqlInjector extends DefaultSqlInjector {
+
+    /**
+     * 如果只需增加方法,保留mybatis plus自带方法,
+     * 可以先获取super.getMethodList(),再添加add
+     */
+    @Override
+    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
+        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
+        methodList.add(new InsertBatch());
+        methodList.add(new UpdateBatch());
+        methodList.add(new InsertOrUpdateBath());
+        return methodList;
+    }
+}

+ 63 - 0
themis-business/src/main/java/com/qmth/themis/business/base/InsertBatch.java

@@ -0,0 +1,63 @@
+package com.qmth.themis.business.base;
+
+import com.baomidou.mybatisplus.core.injector.AbstractMethod;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import org.apache.ibatis.executor.keygen.NoKeyGenerator;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @Description: 自定义批量插入
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/5/11
+ */
+public class InsertBatch extends AbstractMethod {
+    private final static Logger log = LoggerFactory.getLogger(InsertBatch.class);
+
+    /**
+     * insert into user(id, name, age) values (1, "a", 17), (2, "b", 18);
+     * <script>
+     * insert into user(id, name, age) values
+     * <foreach collection="collection" item="item" index="index" open="(" separator="),(" close=")">
+     * #{item.id}, #{item.name}, #{item.age}
+     * </foreach>
+     * </script>
+     */
+    @Override
+    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
+        final String sql = "<script>insert into %s %s values %s</script>";
+        final String fieldSql = prepareFieldSql(tableInfo);
+        final String valueSql = prepareValuesSql(tableInfo);
+        final String sqlResult = String.format(sql, tableInfo.getTableName(), fieldSql, valueSql);
+        log.debug("sqlResult----->{}", sqlResult);
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
+        // 第三个参数必须和RootMapper的自定义方法名一致
+        return this.addInsertMappedStatement(mapperClass, modelClass, "insertBatch", sqlSource, new NoKeyGenerator(), null, null);
+    }
+
+    private String prepareFieldSql(TableInfo tableInfo) {
+        StringBuilder fieldSql = new StringBuilder();
+        fieldSql.append(tableInfo.getKeyColumn()).append(",");
+        tableInfo.getFieldList().forEach(x -> {
+            fieldSql.append(x.getColumn()).append(",");
+        });
+        fieldSql.delete(fieldSql.length() - 1, fieldSql.length());
+        fieldSql.insert(0, "(");
+        fieldSql.append(")");
+        return fieldSql.toString();
+    }
+
+    private String prepareValuesSql(TableInfo tableInfo) {
+        final StringBuilder valueSql = new StringBuilder();
+        valueSql.append("<foreach collection=\"collection\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");
+        valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},");
+        tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));
+        valueSql.delete(valueSql.length() - 1, valueSql.length());
+        valueSql.append("</foreach>");
+        return valueSql.toString();
+    }
+}

+ 85 - 0
themis-business/src/main/java/com/qmth/themis/business/base/InsertOrUpdateBath.java

@@ -0,0 +1,85 @@
+package com.qmth.themis.business.base;
+
+import com.baomidou.mybatisplus.core.injector.AbstractMethod;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import org.apache.ibatis.executor.keygen.NoKeyGenerator;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.StringUtils;
+
+/**
+ * @Description: 自定义插入或更新
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/5/11
+ */
+public class InsertOrUpdateBath extends AbstractMethod {
+    private final static Logger log = LoggerFactory.getLogger(InsertOrUpdateBath.class);
+
+    @Override
+    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
+        final String sql = "<script>insert into %s %s values %s ON DUPLICATE KEY UPDATE %s</script>";
+        final String tableName = tableInfo.getTableName();
+        final String filedSql = prepareFieldSql(tableInfo);
+        final String modelValuesSql = prepareModelValuesSql(tableInfo);
+        final String duplicateKeySql = prepareDuplicateKeySql(tableInfo);
+        final String sqlResult = String.format(sql, tableName, filedSql, modelValuesSql, duplicateKeySql);
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
+        return this.addInsertMappedStatement(mapperClass, modelClass, "insertOrUpdateBath", sqlSource, new NoKeyGenerator(), null, null);
+    }
+
+    /**
+     * 准备ON DUPLICATE KEY UPDATE sql
+     *
+     * @param tableInfo
+     * @return
+     */
+    private String prepareDuplicateKeySql(TableInfo tableInfo) {
+        final StringBuilder duplicateKeySql = new StringBuilder();
+        if (!StringUtils.isEmpty(tableInfo.getKeyColumn())) {
+            duplicateKeySql.append(tableInfo.getKeyColumn()).append("=values(").append(tableInfo.getKeyColumn()).append("),");
+        }
+
+        tableInfo.getFieldList().forEach(x -> {
+            duplicateKeySql.append(x.getColumn())
+                    .append("=values(")
+                    .append(x.getColumn())
+                    .append("),");
+        });
+        duplicateKeySql.delete(duplicateKeySql.length() - 1, duplicateKeySql.length());
+        return duplicateKeySql.toString();
+    }
+
+    /**
+     * 准备属性名
+     *
+     * @param tableInfo
+     * @return
+     */
+    private String prepareFieldSql(TableInfo tableInfo) {
+        StringBuilder fieldSql = new StringBuilder();
+        fieldSql.append(tableInfo.getKeyColumn()).append(",");
+        tableInfo.getFieldList().forEach(x -> {
+            fieldSql.append(x.getColumn()).append(",");
+        });
+        fieldSql.delete(fieldSql.length() - 1, fieldSql.length());
+        fieldSql.insert(0, "(");
+        fieldSql.append(")");
+        return fieldSql.toString();
+    }
+
+    private String prepareModelValuesSql(TableInfo tableInfo) {
+        final StringBuilder valueSql = new StringBuilder();
+        valueSql.append("<foreach collection=\"collection\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");
+        if (!StringUtils.isEmpty(tableInfo.getKeyProperty())) {
+            valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},");
+        }
+        tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));
+        valueSql.delete(valueSql.length() - 1, valueSql.length());
+        valueSql.append("</foreach>");
+        return valueSql.toString();
+    }
+}

+ 30 - 0
themis-business/src/main/java/com/qmth/themis/business/base/UpdateBatch.java

@@ -0,0 +1,30 @@
+package com.qmth.themis.business.base;
+
+import com.baomidou.mybatisplus.core.injector.AbstractMethod;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @Description: 自定义更新
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/5/11
+ */
+public class UpdateBatch extends AbstractMethod {
+    private final static Logger log = LoggerFactory.getLogger(UpdateBatch.class);
+
+    @Override
+    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
+        String sql = "<script>\n<foreach collection=\"collection\" item=\"item\" separator=\";\">\nupdate %s %s where %s=#{%s} %s\n</foreach>\n</script>";
+        String additional = tableInfo.isWithVersion() ? tableInfo.getVersionFieldInfo().getVersionOli("item", "item.") : "" + tableInfo.getLogicDeleteSql(true, true);
+        String setSql = sqlSet(tableInfo.isWithLogicDelete(), false, tableInfo, false, "item", "item.");
+        String sqlResult = String.format(sql, tableInfo.getTableName(), setSql, tableInfo.getKeyColumn(), "item." + tableInfo.getKeyProperty(), additional);
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
+        // 第三个参数必须和RootMapper的自定义方法名一致
+        return this.addUpdateMappedStatement(mapperClass, modelClass, "updateBatch", sqlSource);
+    }
+}

+ 13 - 0
themis-business/src/main/java/com/qmth/themis/business/config/MybatisPlusConfig.java

@@ -5,10 +5,18 @@ import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
 import com.baomidou.mybatisplus.core.config.GlobalConfig;
 import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import com.qmth.themis.business.base.CustomizedSqlInjector;
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
+/**
+ * @Description: mybatis-plus配置
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/5/11
+ */
 @Configuration
 @MapperScan(basePackages = {"com.qmth.themis.business.dao"})
 public class MybatisPlusConfig {
@@ -36,4 +44,9 @@ public class MybatisPlusConfig {
     public ConfigurationCustomizer configurationCustomizer() {
         return configuration -> configuration.setUseDeprecatedExecutor(false);
     }
+
+    @Bean
+    public CustomizedSqlInjector customizedSqlInjector() {
+        return new CustomizedSqlInjector();
+    }
 }

+ 2 - 1
themis-business/src/main/java/com/qmth/themis/business/dao/TBExamInvigilateUserMapper.java

@@ -2,6 +2,7 @@ package com.qmth.themis.business.dao;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.qmth.themis.business.base.CustomBaseMapper;
 import com.qmth.themis.business.dto.RoomCodeExportDto;
 import com.qmth.themis.business.dto.response.TBExamInvigilateUserDto;
 import com.qmth.themis.business.entity.TBExamInvigilateUser;
@@ -19,7 +20,7 @@ import java.util.Map;
  * @Date: 2020/7/9
  */
 @Mapper
-public interface TBExamInvigilateUserMapper extends BaseMapper<TBExamInvigilateUser> {
+public interface TBExamInvigilateUserMapper extends CustomBaseMapper<TBExamInvigilateUser> {
 
     /**
      * 查询监考员

+ 2 - 1
themis-business/src/main/java/com/qmth/themis/business/dao/TBUserMapper.java

@@ -2,6 +2,7 @@ package com.qmth.themis.business.dao;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.qmth.themis.business.base.CustomBaseMapper;
 import com.qmth.themis.business.dto.response.TBUserDto;
 import com.qmth.themis.business.entity.TBUser;
 import org.apache.ibatis.annotations.Mapper;
@@ -17,7 +18,7 @@ import java.util.Map;
  * @Date: 2020/6/25
  */
 @Mapper
-public interface TBUserMapper extends BaseMapper<TBUser> {
+public interface TBUserMapper extends CustomBaseMapper<TBUser> {
 
     /**
      * 用户查询

+ 2 - 1
themis-business/src/main/java/com/qmth/themis/business/dao/TBUserRoleMapper.java

@@ -1,6 +1,7 @@
 package com.qmth.themis.business.dao;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.qmth.themis.business.base.CustomBaseMapper;
 import com.qmth.themis.business.entity.TBUser;
 import com.qmth.themis.business.entity.TBUserRole;
 import org.apache.ibatis.annotations.Mapper;
@@ -16,7 +17,7 @@ import java.util.List;
  * @Date: 2020/6/25
  */
 @Mapper
-public interface TBUserRoleMapper extends BaseMapper<TBUserRole> {
+public interface TBUserRoleMapper extends CustomBaseMapper<TBUserRole> {
 
     /**
      * 根据机构id+角色查询用户

+ 2 - 1
themis-business/src/main/java/com/qmth/themis/business/dao/TEExamCourseMapper.java

@@ -3,6 +3,7 @@ package com.qmth.themis.business.dao;
 import java.util.List;
 import java.util.Map;
 
+import com.qmth.themis.business.base.CustomBaseMapper;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
@@ -20,7 +21,7 @@ import com.qmth.themis.business.entity.TEExamCourse;
  * @Date: 2020/6/25
  */
 @Mapper
-public interface TEExamCourseMapper extends BaseMapper<TEExamCourse> {
+public interface TEExamCourseMapper extends CustomBaseMapper<TEExamCourse> {
 
     /**
      * 查询考试科目

+ 2 - 1
themis-business/src/main/java/com/qmth/themis/business/dao/TEExamStudentMapper.java

@@ -2,6 +2,7 @@ package com.qmth.themis.business.dao;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.qmth.themis.business.base.CustomBaseMapper;
 import com.qmth.themis.business.bean.admin.ExamDeficiencyListBean;
 import com.qmth.themis.business.bean.admin.ExamStudentLogListBean;
 import com.qmth.themis.business.bean.admin.ExamViewCountListBean;
@@ -24,7 +25,7 @@ import java.util.Map;
  * @Date: 2020/6/25
  */
 @Mapper
-public interface TEExamStudentMapper extends BaseMapper<TEExamStudent> {
+public interface TEExamStudentMapper extends CustomBaseMapper<TEExamStudent> {
 
     /**
      * 查询考生信息

+ 2 - 1
themis-business/src/main/java/com/qmth/themis/business/dao/TEStudentMapper.java

@@ -2,6 +2,7 @@ package com.qmth.themis.business.dao;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.qmth.themis.business.base.CustomBaseMapper;
 import com.qmth.themis.business.dto.response.TEStudentDto;
 import com.qmth.themis.business.dto.response.TEStudentExamRecordDto;
 import com.qmth.themis.business.entity.TEStudent;
@@ -18,7 +19,7 @@ import java.util.Map;
  * @Date: 2020/6/25
  */
 @Mapper
-public interface TEStudentMapper extends BaseMapper<TEStudent> {
+public interface TEStudentMapper extends CustomBaseMapper<TEStudent> {
 
     /**
      * 学生档案查询

+ 25 - 9
themis-business/src/main/java/com/qmth/themis/business/templete/service/impl/TempleteLogicServiceImpl.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.google.gson.Gson;
 import com.qmth.themis.business.cache.bean.ExamCourseCacheBean;
 import com.qmth.themis.business.constant.SystemConstant;
+import com.qmth.themis.business.dao.*;
 import com.qmth.themis.business.dto.ExamStudentImportDto;
 import com.qmth.themis.business.dto.RoomCodeImportDto;
 import com.qmth.themis.business.entity.*;
@@ -50,10 +51,25 @@ public class TempleteLogicServiceImpl implements TempleteLogicService {
     TBUserService tbUserService;
 
     @Resource
-    TBUserRoleService tbUserRoleService;
+    TEExamCourseService teExamCourseService;
 
     @Resource
-    TEExamCourseService teExamCourseService;
+    TEStudentMapper teStudentMapper;
+
+    @Resource
+    TEExamStudentMapper teExamStudentMapper;
+
+    @Resource
+    TBExamInvigilateUserMapper tbExamInvigilateUserMapper;
+
+    @Resource
+    TEExamCourseMapper teExamCourseMapper;
+
+    @Resource
+    TBUserMapper tbUserMapper;
+
+    @Resource
+    TBUserRoleMapper tbUserRoleMapper;
 
     /**
      * 考生导入逻辑
@@ -92,7 +108,7 @@ public class TempleteLogicServiceImpl implements TempleteLogicService {
             teExamCourses.add(teExamCourse);
         });
         if (teExamCourses.size() > 0) {
-            teExamCourseService.saveBatch(teExamCourses);
+            teExamCourseMapper.insertBatch(teExamCourses);
         }
         TEExamActivity teExamActivity = null;
         ExamModeEnum modeEnum = ExamModeEnum.valueOf(String.valueOf(map.get("mode")));
@@ -186,8 +202,8 @@ public class TempleteLogicServiceImpl implements TempleteLogicService {
                     max = size;
                 }
             }
-            teStudentService.saveOrUpdateBatch(teStudentList);
-            teExamStudentService.saveOrUpdateBatch(teExamStudentList);
+            teStudentMapper.insertOrUpdateBath(teStudentList);
+            teExamStudentMapper.insertOrUpdateBath(teExamStudentList);
         }
         map.put("line", line);
         //考场创建
@@ -203,7 +219,7 @@ public class TempleteLogicServiceImpl implements TempleteLogicService {
                     count.getAndIncrement();
                 }
             });
-            tbExamInvigilateUserService.saveOrUpdateBatch(tbExamInvigilateUserList);
+            tbExamInvigilateUserMapper.insertOrUpdateBath(tbExamInvigilateUserList);
             if (count.get() > 0) {
                 txtList.add(DateUtil.format(new Date(), Constants.DEFAULT_DATE_PATTERN) + "->创建了" + count + "条考场数据");
             }
@@ -276,9 +292,9 @@ public class TempleteLogicServiceImpl implements TempleteLogicService {
                 .in(TBExamInvigilateUser::getRoomName, roomNameSet);
         tbExamInvigilateUserService.remove(wrapper);
 
-        tbUserService.saveOrUpdateBatch(tbUserList);
-        tbUserRoleService.saveOrUpdateBatch(tbUserRoleList);
-        tbExamInvigilateUserService.saveOrUpdateBatch(tbExamInvigilateUserList);
+        tbUserMapper.insertOrUpdateBath(tbUserList);
+        tbUserRoleMapper.insertOrUpdateBath(tbUserRoleList);
+        tbExamInvigilateUserMapper.insertOrUpdateBath(tbExamInvigilateUserList);
         map.put("line", line);
         return map;
     }