shikeyin
2024-01-11 65da8373531677b1c37a98f53eaa30c892f35e5a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package com.iplatform.base.di;
 
import com.iplatform.base.service.DataImportServiceImpl;
import com.iplatform.base.util.DataImportUtils;
import com.iplatform.core.BeanContextAware;
import com.walker.di.BusinessImportException;
import com.walker.di.UpdateResult;
import com.walker.di.UpdateType;
import com.walker.di.excel.ExcelDataImportor;
import com.walker.infrastructure.utils.StringUtils;
 
import java.util.List;
import java.util.Map;
 
/**
 * 基于JDBC操作的导入实现。
 * @author 时克英
 * @date 2023-02-01
 */
//public abstract class JdbcCsvDataImportor extends CsvDataImportor {
public abstract class JdbcExcelDataImportor extends ExcelDataImportor {
 
//    private DataImportServiceImpl dataImportService;
 
    // 更新语句缓存
    private String updateSql = null;
 
    @Override
    protected void saveImportData(List<Object[]> dataList, List<String> fieldNames) throws BusinessImportException {
        if(!this.isCheckDataExist()){
            this.logger.debug("不检查数据是否存在,直接导入, size = " + dataList.size());
            try{
                this.doExecuteInsert(dataList, fieldNames);
            } catch (Exception ex){
                throw new BusinessImportException("保存一次导入错误:" + ex.getMessage(), ex);
            }
            return;
        }
 
        String tableName = this.acquireTableName();
        logger.debug("准备检查数据是否存在");
 
        // 把数据转成Map集合
        List<Map<String, Object>> mapList = DataImportUtils.translateToMap(dataList, fieldNames);
        if(mapList == null){
            logger.error("保存转换数据为空,无法保存: mapList = DataImportUtils.translateTo() == null!");
            return;
        }
 
        UpdateResult updateResult = this.checkDataExist(tableName, mapList);
        if(updateResult == null){
            throw new BusinessImportException("业务检查导入是否存在数据, 但未返回任何内容, 系统无法更新,table=" + tableName, null);
        }
        if(!StringUtils.isEmptyList(updateResult.getInsertList())){
            this.doExecuteInsertMap(updateResult.getInsertList(), fieldNames);
            if(this.logger.isDebugEnabled()){
                this.logger.debug("........ doExecuteInsert():" + updateResult.getInsertList().size());
            }
        }
        if(!StringUtils.isEmptyList(updateResult.getUpdateList())){
            if(StringUtils.isEmptyList(updateResult.getUpdateColumnNames())
                    || StringUtils.isEmptyList(updateResult.getWhereColumnNames())){
                throw new BusinessImportException("导入更新数据,但未发现任何更新字段名称和条件,table=" + tableName, null);
            }
            this.doExecuteUpdateMap(updateResult.getUpdateList()
                    , updateResult.getUpdateColumnNames(), updateResult.getWhereColumnNames(), tableName);
            if(this.logger.isDebugEnabled()){
                this.logger.debug("........ doExecuteUpdate():" + updateResult.getUpdateList().size());
            }
        }
    }
 
    @Override
    protected void saveBrokenInfo(long index) {
        throw new UnsupportedOperationException("暂未实现断点续传功能");
    }
 
    /**
     * 实际写入操作,注意: 这里 dataList 里面Map是无序的,需要配合字段列使用。
     * @param mapList
     * @param fieldNames
     * @date 2023-02-06
     */
    private void doExecuteInsertMap(List<Map<String, Object>> mapList, List<String> fieldNames){
        String insertSql = this.getInsertSql(fieldNames);
        List<Object[]> dataList = DataImportUtils.translateToArray(mapList, fieldNames);
        if(StringUtils.isEmptyList(dataList)){
            logger.debug("无法执行doExecuteInsertMap: DataImportUtils.translateToArray = null.");
            return;
        }
        this.getDataImportService().execBatchUpdate(insertSql, dataList);
    }
 
    /**
     * 实际更新操作,注意: 这里 dataList 里面Map是无序的,需要配合字段列使用。
     * @param dataList
     * @param updateColumns 要更新的字段集合
     * @param whereColumns 更新条件集合
     */
    private void doExecuteUpdateMap(List<Map<String, Object>> dataList
            , List<String> updateColumns, List<String> whereColumns, String tableName){
        if(this.getUpdateType() == UpdateType.Override){
            logger.debug("设置的更新策略: Override");
            if(StringUtils.isEmptyList(updateColumns) || StringUtils.isEmptyList(whereColumns)){
                throw new IllegalArgumentException("导入'无法更新数据': updateColumns or whereColumns 为空!");
            }
 
            List<Object[]> parameters = DataImportUtils.acquireUpdateValues(dataList, updateColumns, whereColumns);
            if(StringUtils.isEmptyList(parameters)){
//                throw new IllegalArgumentException("未找到更新值集合,导入数据更新失败! parameters=null");
                logger.debug("未找到更新值集合,不更新记录");
                return;
            }
            if(this.updateSql == null){
                this.updateSql = DataImportUtils.acquireUpdateSql(tableName, updateColumns, whereColumns);
                if(this.logger.isDebugEnabled()){
                    this.logger.debug("更新SQL = " + this.updateSql);
                }
            }
 
            this.getDataImportService().execBatchUpdate(this.updateSql, parameters);
        }
    }
 
    /**
     * 写入新数据。
     * @param dataList
     * @param fieldNames
     * @date 2023-02-01
     * @date 2023-05-07 方法提升为保护,让子类可以重写该方法。
     */
    protected void doExecuteInsert(List<Object[]> dataList, List<String> fieldNames){
//        String tableName = this.acquireTableName();
//        if(StringUtils.isEmpty(tableName)){
//            throw new UnsupportedOperationException("必须实现方法: acquireTableName");
//        }
//        String insertSQL = DataImportUtils.acquireInsertSql(tableName, fieldNames);
//        this.dataImportService.execBatchUpdate(insertSQL, dataList);
        this.getDataImportService().execBatchUpdate(this.getInsertSql(fieldNames), dataList);
    }
 
    private String getInsertSql(List<String> fieldNames){
        String tableName = this.acquireTableName();
        if(StringUtils.isEmpty(tableName)){
            throw new UnsupportedOperationException("必须实现方法: acquireTableName");
        }
        return DataImportUtils.acquireInsertSql(tableName, fieldNames);
    }
 
//    public void setDataImportService(DataImportServiceImpl dataImportService) {
//        this.dataImportService = dataImportService;
//    }
 
    public DataImportServiceImpl getDataImportService() {
//        return dataImportService;
        return BeanContextAware.getBeanByType(DataImportServiceImpl.class);
    }
 
    /**
     * 返回要写入的表名
     * @return
     */
    protected abstract String acquireTableName();
 
    /**
     * 写入之前,是否检查数据已存在
     * @return
     */
    protected abstract boolean isCheckDataExist();
 
    /**
     * 检测该批数据在数据库中是否存在。
     * <pre>
     *     1)该方法需要子类处理具体查询过程,通常只有一个条件的话可以使用 where id in (columns)的方式。
     *     2)如果条件多个,就需要业务通过多个 where in 方式,如: where name in (:names) and card in (:cards)。
     *     3)
     * </pre>
     * @param mapList
//     * @param fieldNames
     * @return 返回一个更新结果对象。
     */
    protected abstract UpdateResult checkDataExist(String tableName, List<Map<String, Object>> mapList);
}