ny
23 小时以前 b6f169fe43a2b13f351aefc152374fc7f0bc8cb7
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
package jnpf.base.service.impl;
 
import com.google.common.collect.ImmutableMap;
import jnpf.base.Page;
import jnpf.base.Pagination;
import jnpf.base.service.DbLinkService;
import jnpf.base.service.DbTableService;
import jnpf.constant.MsgCode;
import jnpf.database.datatype.db.DtDMEnum;
import jnpf.database.datatype.db.interfaces.DtInterface;
import jnpf.database.datatype.viewshow.ViewDataTypeEnum;
import jnpf.database.datatype.viewshow.constant.DtViewConst;
import jnpf.database.enums.DbAliasEnum;
import jnpf.database.model.dbfield.DbFieldModel;
import jnpf.database.model.dbtable.DbTableFieldModel;
import jnpf.database.model.dto.PrepSqlDTO;
import jnpf.database.model.entity.DbLinkEntity;
import jnpf.database.model.page.DbTableDataForm;
import jnpf.database.model.page.JdbcPageMod;
import jnpf.database.source.DbBase;
import jnpf.database.source.impl.DbPostgre;
import jnpf.database.sql.enums.base.SqlComEnum;
import jnpf.database.sql.util.SqlFastUtil;
import jnpf.database.sql.util.SqlFrameUtil;
import jnpf.database.util.DbTypeUtil;
import jnpf.database.util.JdbcUtil;
import jnpf.database.util.NotTenantPluginHolder;
import jnpf.database.util.TableUtil;
import jnpf.exception.DataException;
import jnpf.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
 
/**
 * 数据管理
 *
 * @author JNPF开发平台组
 * @version V3.1.0
 * @copyright 引迈信息技术有限公司
 * @date 2019年9月27日 上午9:18
 */
@Slf4j
@Service
public class DbTableServiceImpl implements DbTableService {
 
    @Autowired
    private DbLinkService dblinkService;
 
    @Override
    public List<DbTableFieldModel> getList(String dbLinkId, String methodName) throws Exception {
        DbLinkEntity dbLinkEntity = dblinkService.getResource(dbLinkId);
        return SqlFastUtil.getTableList(dbLinkEntity, methodName);
    }
 
    @Override
    public List<DbTableFieldModel> getListPage(String dbLinkId, Page page) throws Exception {
        List<DbTableFieldModel> list = getList(dbLinkId, DbAliasEnum.TABLE_TYPE.getAlias());
        if(StringUtil.isNotEmpty(page.getKeyword())){
            // 过滤不符条件的元素
            String keyWord = SqlFrameUtil.keyWordTrim(page.getKeyword()).toLowerCase();
            list = list.stream().filter(t->
                    (StringUtil.isNotEmpty(t.getComment()) && t.getComment().toLowerCase().contains(keyWord))
                            || t.getTable().toLowerCase().contains(keyWord)
            ).collect(Collectors.toList());
        }
        return list;
    }
 
    @Override
    public List<DbTableFieldModel> getListPage(String dbLinkId, Pagination pagination) throws Exception {
        List<DbTableFieldModel> list = getList(dbLinkId, null);
        if(StringUtil.isNotEmpty(pagination.getKeyword())){
            // 过滤不符条件的元素
            String keyWord = SqlFrameUtil.keyWordTrim(pagination.getKeyword()).toLowerCase();
            list = list.stream().filter(t->
                    (StringUtil.isNotEmpty(t.getComment()) && t.getComment().toLowerCase().contains(keyWord))
                            || t.getTable().toLowerCase().contains(keyWord)
            ).collect(Collectors.toList());
        }
        long beginIndex = (pagination.getCurrentPage() -1) * pagination.getPageSize();
        long endIndex = beginIndex + pagination.getPageSize();
        List<DbTableFieldModel> listVO = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            if(beginIndex <= i && i < endIndex){
                listVO.add(list.get(i));
            }
        }
        pagination.setTotal(list.size());
        return listVO;
    }
 
    @Override
    public DbTableFieldModel getTable(String dbLinkId, String table) throws Exception {
        DbLinkEntity dbLinkEntity = dblinkService.getResource(dbLinkId);
        DbTableFieldModel dbTableFieldModel = SqlFastUtil.getTable(dbLinkEntity, table);
        dbTableFieldModel.setHasTableData(getSum(dbLinkId, table) > 0);
        return dbTableFieldModel;
    }
 
    @Override
    public List<DbFieldModel> getFieldList(String dbLinkId, String table) throws Exception {
        DbLinkEntity dbLinkEntity = dblinkService.getResource(dbLinkId);
        return SqlFastUtil.getFieldList(dbLinkEntity, table);
    }
 
    @Override
    public boolean isExistTable(String dbLinkId, String table) throws Exception {
        DbLinkEntity dbLinkEntity = dblinkService.getResource(dbLinkId);
        return SqlFastUtil.isExistTable(dbLinkEntity, table);
    }
 
    @Override
    public boolean dropExistsTable(String dbLinkId, String table) throws Exception {
        DbLinkEntity dbLinkEntity = dblinkService.getResource(dbLinkId);
        if(isExistTable(dbLinkId, table)){
            return SqlFastUtil.dropTable(dbLinkEntity, table);
        }
        return true;
    }
 
    @Override
    public List<Map<String, Object>> getData(DbTableDataForm dbTableDataForm, String dbLinkId, String table) throws Exception {
        DbLinkEntity dbLinkEntity = dblinkService.getResource(dbLinkId);
        JdbcPageMod result = new JdbcPageMod();
        String orderKey = dbTableDataForm.getField();
        // 防止SQL注入
        String finalOrderKey = orderKey;
        if(getFieldList(dbLinkId, table).stream().noneMatch(field -> field.getField().equals(finalOrderKey))){
            throw  new DataException("排序字段不存在");
        }
        if (dbLinkEntity != null) {
            List<Object> dataList = new ArrayList<>();
            if(DbTypeUtil.checkPostgre(dbLinkEntity)){
                table = DbPostgre.getTable(table);
                orderKey = DbPostgre.getTable(orderKey);
//                String schema = dbLinkEntity.getDbSchema();
//                if(StringUtil.isNotEmpty(schema)){
//                    table = schema + "." + table;
//                }
            }
            StringBuilder sql = new StringBuilder(SqlComEnum.SELECT_TABLE.getOutSql(table));
            //模糊查询
            if (!StringUtil.isEmpty(dbTableDataForm.getKeyword()) && !StringUtil.isEmpty(orderKey)) {
                sql.append(" where " + orderKey + " like ?");
                dataList.add("%" + SqlFrameUtil.keyWordTrim(dbTableDataForm.getKeyword()) + "%");
            }
            result = JdbcUtil.queryPage(
                    new PrepSqlDTO(sql.toString(), dataList).withConn(dbLinkEntity),
                    checkOrderKey(orderKey, dbLinkId, table, dbLinkEntity.getDbType()),
                    (int) dbTableDataForm.getCurrentPage(),
                    (int) dbTableDataForm.getPageSize())
                    .setIsLowerCase(true).setIsAlias(true).get();
        }
        dbTableDataForm.setTotal(result.getTotalRecord());
        return (List<Map<String, Object>>)result.getDataList();
    }
 
    private String checkOrderKey(String orderKey, String dbLinkId, String table, String dbEncode){
        try {
            if(DbBase.DM.equals(dbEncode)){
                List<DbFieldModel> fieldList = getFieldList(dbLinkId, table);
                Optional<DbFieldModel> first = fieldList.stream().filter(field -> field.getField().equals(orderKey)).findFirst();
                if(first.isPresent()){
                    String dataType = first.get().getDataType();
                    if(dataType.equals(DtDMEnum.CLOB.getDataType()) || dataType.equals(DtDMEnum.TEXT.getDataType())){
//                        throw new Exception("无法使用CLOB、TEXT作为字段排序条件");
                        Optional<DbFieldModel> first1 = fieldList.stream().filter(field -> field.getField().toLowerCase().contains("id")).findFirst();
                        if(first1.isPresent()){
                            return first1.get().getField();
                        }
 
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return orderKey;
    }
 
    @Override
    public int getSum(String dbLinkId,String table)throws Exception {
        DbLinkEntity dbLinkEntity = dblinkService.getResource(dbLinkId);
        return SqlFastUtil.getSum(dbLinkEntity, table);
    }
 
    /**=====================增删改========================**/
 
    @Override
    public void delete(String dbLinkId, String table) throws Exception {
        // 校验
        checkTab(table, dbLinkId, 1);
        SqlFastUtil.dropTable(dblinkService.getResource(dbLinkId), table);
    }
 
    @Override
    public void deleteAllTable(String dbLinkId, String dbType) throws Exception {
        DbLinkEntity dbLinkEntity = dblinkService.getResource(dbLinkId);
        if(!dbLinkEntity.getDbType().equals(dbType)) throw new Exception("数据库类型不符");
        for (DbTableFieldModel dbTableFieldModel : SqlFastUtil.getTableList(dbLinkEntity)) {
            SqlFastUtil.dropTable(dbLinkEntity, dbTableFieldModel.getTable());
        }
    }
 
    @Override
    public int createTable(DbTableFieldModel dbTableFieldModel) throws Exception {
        DbLinkEntity dbLinkEntity = dblinkService.getResource(dbTableFieldModel.getDbLinkId());
        // 数据库编码查询校验 (打印模板校验)
        String opeDb = dbLinkEntity.getDbType();
        String creDb =  dbTableFieldModel.getDbEncode();
        if(StringUtil.isNotEmpty(creDb)  && !creDb.equals(opeDb)){
            throw new DataException(MsgCode.DB008.get() + ":" + creDb +  " -> " + opeDb);
        }
        // 表重名判断
        if (isExistTable(dbTableFieldModel.getDbLinkId(), dbTableFieldModel.getTable())) {
            return 0;
        }
        // 表主键检验
        checkPrimary(dbTableFieldModel.getDbFieldModelList(), dbLinkEntity.getDbType());
        // 创建表
        SqlFastUtil.creTable(dbLinkEntity, dbTableFieldModel);
        return 1;
    }
 
    @Override
    public void update(DbTableFieldModel dbTableFieldModel) throws Exception {
        // 校验
        checkTab(dbTableFieldModel.getUpdateOldTable(), dbTableFieldModel.getDbLinkId(), 2);
        DbLinkEntity dbLinkEntity = dblinkService.getResource(dbTableFieldModel.getDbLinkId());
        //临时表名
        String oldTable = dbTableFieldModel.getUpdateOldTable();
        String newTable = dbTableFieldModel.getUpdateNewTable();
        String tempTabName = "Temp_" + TableUtil.getStringRandom(5);
        // 第一步:创建新表 (成功则删除旧表,失败则回滚)
        checkPrimary(dbTableFieldModel.getDbFieldModelList(), dbLinkEntity.getDbType());
        SqlFastUtil.creTable(dbLinkEntity,
                new DbTableFieldModel(
                        tempTabName,
                        dbTableFieldModel.getComment(),
                        dbTableFieldModel.getDbFieldModelList()
                ));
        // 第二步:删除旧表
        SqlFastUtil.dropTable(dbLinkEntity, oldTable);
        // 第三步:新表改名
        SqlFastUtil.reTableName(dbLinkEntity, tempTabName, newTable);
    }
 
    @Override
    public void addField(DbTableFieldModel dbTableFieldModel) throws Exception {
        DbLinkEntity dbLinkEntity = dblinkService.getResource(dbTableFieldModel.getDbLinkId());
        SqlFastUtil.addField(dbLinkEntity, dbTableFieldModel.getUpdateNewTable(), dbTableFieldModel.getDbFieldModelList());
    }
 
    @Override
    public DbTableFieldModel getDbTableModel(String dbLinkId, String tableName)throws Exception {
        NotTenantPluginHolder.setNotSwitchFlag();
        DbTableFieldModel dbTableModel = getList(dbLinkId, null).stream().filter(m -> m.getTable().equals(tableName)).findFirst().orElse(null);
        if(dbTableModel != null){
            dbTableModel.setDbFieldModelList(getFieldList(dbLinkId, tableName));
            return dbTableModel;
        }else {
            throw new DataException("请在数据库中添加对应的数据表");
        }
    }
 
    /* ================复用代码================== */
 
    /**
     * 校验表可操作
     *
     * @param table 表
     * @param dbLinkId 数据连接ID
     * @param type 1:删除 2:编辑
     * @throws Exception 错误信息
     */
    private void checkTab(String table, String dbLinkId, Integer type) throws Exception {
        if (TableUtil.checkByoTable(table)) throw new DataException(type == 1 ? MsgCode.DB101.get() : MsgCode.DB102.get());
        if (getSum(dbLinkId, table) > 0) throw new DataException(type == 1 ? MsgCode.DB201.get() : MsgCode.DB202.get());
    }
 
    /**
     * 检查主键
     * @param tableFieldList  表字段集合
     * @throws DataException ignore
     */
    private void checkPrimary(List<DbFieldModel> tableFieldList, String dbEncode) throws Exception {
        // 默认主键为字符串类型
        // 主键会自动添加"非空"限制,所以不用做判断。(为空不加语句,且数据库默认字段可为空)
        int autoIncrementNum = 0;
        for(DbFieldModel field : tableFieldList) {
            if(field.getIsAutoIncrement() != null && field.getIsAutoIncrement()){
                field.setNullSign("NOT NULL");
                // 一张表最多只有一个自增主键,且此字段必须为primary key或者unique key。
                autoIncrementNum += 1;
                if(autoIncrementNum > 1){
                    throw new DataException("一张表最多只运行有一个自增主键");
                }
                if(!(field.getDataType().equals(DtViewConst.INT) || field.getDataType().equals(DtViewConst.BIGINT))){
                    throw new DataException("自增字段类型必须为数字类型");
                }
                if(!field.getIsPrimaryKey()){
                    throw new DataException("自增字段类型必须为主键");
                }
            }else {
                if (field.getIsPrimaryKey()) {
                    field.setNullSign("NOT NULL");
                    Method method = ViewDataTypeEnum.class.getMethod("getDt" + dbEncode + "Enum");
                    Map<ViewDataTypeEnum, String> allowDtMap = ImmutableMap.of(
                            ViewDataTypeEnum.VARCHAR, DtViewConst.VARCHAR,
                            ViewDataTypeEnum.INT, DtViewConst.INT,
                            ViewDataTypeEnum.BIGINT, DtViewConst.BIGINT
                    );
                    boolean primaryFlag = false;
                    for (Map.Entry<ViewDataTypeEnum, String> mapEntity : allowDtMap.entrySet()) {
                        DtInterface primaryVarcharEnum = (DtInterface)(method.invoke(mapEntity.getKey()));
                        boolean enumFlag = field.getDataType().equalsIgnoreCase(primaryVarcharEnum.getDataType());
                        boolean viewFlag = field.getDataType().equalsIgnoreCase(mapEntity.getValue());
                        if(enumFlag || viewFlag){
                            primaryFlag = true;
                        }
                    }
                    if(!primaryFlag){
                        throw new DataException("主键必须为字符串或整型、长整型");
                    }
                }
            }
        }
    }
 
}