懒羊羊
2024-01-31 e57a8990ae56f657a59c435a0613c5f7a8728003
提交 | 用户 | 时间
e57a89 1 package com.jcdm.generator.service;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.File;
5 import java.io.IOException;
6 import java.io.StringWriter;
7 import java.util.LinkedHashMap;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.function.Function;
11 import java.util.stream.Collectors;
12 import java.util.zip.ZipEntry;
13 import java.util.zip.ZipOutputStream;
14 import org.apache.commons.io.FileUtils;
15 import org.apache.commons.io.IOUtils;
16 import org.apache.velocity.Template;
17 import org.apache.velocity.VelocityContext;
18 import org.apache.velocity.app.Velocity;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21 import org.springframework.beans.factory.annotation.Autowired;
22 import org.springframework.stereotype.Service;
23 import org.springframework.transaction.annotation.Transactional;
24 import com.alibaba.fastjson2.JSON;
25 import com.alibaba.fastjson2.JSONObject;
26 import com.jcdm.common.constant.Constants;
27 import com.jcdm.common.constant.GenConstants;
28 import com.jcdm.common.core.text.CharsetKit;
29 import com.jcdm.common.exception.ServiceException;
30 import com.jcdm.common.utils.SecurityUtils;
31 import com.jcdm.common.utils.StringUtils;
32 import com.jcdm.generator.domain.GenTable;
33 import com.jcdm.generator.domain.GenTableColumn;
34 import com.jcdm.generator.mapper.GenTableColumnMapper;
35 import com.jcdm.generator.mapper.GenTableMapper;
36 import com.jcdm.generator.util.GenUtils;
37 import com.jcdm.generator.util.VelocityInitializer;
38 import com.jcdm.generator.util.VelocityUtils;
39
40 /**
41  * 业务 服务层实现
42  * 
43  * @author jc
44  */
45 @Service
46 public class GenTableServiceImpl implements IGenTableService
47 {
48     private static final Logger log = LoggerFactory.getLogger(GenTableServiceImpl.class);
49
50     @Autowired
51     private GenTableMapper genTableMapper;
52
53     @Autowired
54     private GenTableColumnMapper genTableColumnMapper;
55
56     /**
57      * 查询业务信息
58      * 
59      * @param id 业务ID
60      * @return 业务信息
61      */
62     @Override
63     public GenTable selectGenTableById(Long id)
64     {
65         GenTable genTable = genTableMapper.selectGenTableById(id);
66         setTableFromOptions(genTable);
67         return genTable;
68     }
69
70     /**
71      * 查询业务列表
72      * 
73      * @param genTable 业务信息
74      * @return 业务集合
75      */
76     @Override
77     public List<GenTable> selectGenTableList(GenTable genTable)
78     {
79         return genTableMapper.selectGenTableList(genTable);
80     }
81
82     /**
83      * 查询据库列表
84      * 
85      * @param genTable 业务信息
86      * @return 数据库表集合
87      */
88     @Override
89     public List<GenTable> selectDbTableList(GenTable genTable)
90     {
91         return genTableMapper.selectDbTableList(genTable);
92     }
93
94     /**
95      * 查询据库列表
96      * 
97      * @param tableNames 表名称组
98      * @return 数据库表集合
99      */
100     @Override
101     public List<GenTable> selectDbTableListByNames(String[] tableNames)
102     {
103         return genTableMapper.selectDbTableListByNames(tableNames);
104     }
105
106     /**
107      * 查询所有表信息
108      * 
109      * @return 表信息集合
110      */
111     @Override
112     public List<GenTable> selectGenTableAll()
113     {
114         return genTableMapper.selectGenTableAll();
115     }
116
117     /**
118      * 修改业务
119      * 
120      * @param genTable 业务信息
121      * @return 结果
122      */
123     @Override
124     @Transactional
125     public void updateGenTable(GenTable genTable)
126     {
127         String options = JSON.toJSONString(genTable.getParams());
128         genTable.setOptions(options);
129         int row = genTableMapper.updateGenTable(genTable);
130         if (row > 0)
131         {
132             for (GenTableColumn cenTableColumn : genTable.getColumns())
133             {
134                 genTableColumnMapper.updateGenTableColumn(cenTableColumn);
135             }
136         }
137     }
138
139     /**
140      * 删除业务对象
141      * 
142      * @param tableIds 需要删除的数据ID
143      * @return 结果
144      */
145     @Override
146     @Transactional
147     public void deleteGenTableByIds(Long[] tableIds)
148     {
149         genTableMapper.deleteGenTableByIds(tableIds);
150         genTableColumnMapper.deleteGenTableColumnByIds(tableIds);
151     }
152
153     /**
154      * 导入表结构
155      * 
156      * @param tableList 导入表列表
157      */
158     @Override
159     @Transactional
160     public void importGenTable(List<GenTable> tableList)
161     {
162         String operName = SecurityUtils.getUsername();
163         try
164         {
165             for (GenTable table : tableList)
166             {
167                 String tableName = table.getTableName();
168                 GenUtils.initTable(table, operName);
169                 int row = genTableMapper.insertGenTable(table);
170                 if (row > 0)
171                 {
172                     // 保存列信息
173                     List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
174                     for (GenTableColumn column : genTableColumns)
175                     {
176                         GenUtils.initColumnField(column, table);
177                         genTableColumnMapper.insertGenTableColumn(column);
178                     }
179                 }
180             }
181         }
182         catch (Exception e)
183         {
184             throw new ServiceException("导入失败:" + e.getMessage());
185         }
186     }
187
188     /**
189      * 预览代码
190      * 
191      * @param tableId 表编号
192      * @return 预览数据列表
193      */
194     @Override
195     public Map<String, String> previewCode(Long tableId)
196     {
197         Map<String, String> dataMap = new LinkedHashMap<>();
198         // 查询表信息
199         GenTable table = genTableMapper.selectGenTableById(tableId);
200         // 设置主子表信息
201         setSubTable(table);
202         // 设置主键列信息
203         setPkColumn(table);
204         VelocityInitializer.initVelocity();
205
206         VelocityContext context = VelocityUtils.prepareContext(table);
207
208         // 获取模板列表
209         List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
210         for (String template : templates)
211         {
212             // 渲染模板
213             StringWriter sw = new StringWriter();
214             Template tpl = Velocity.getTemplate(template, Constants.UTF8);
215             tpl.merge(context, sw);
216             dataMap.put(template, sw.toString());
217         }
218         return dataMap;
219     }
220
221     /**
222      * 生成代码(下载方式)
223      * 
224      * @param tableName 表名称
225      * @return 数据
226      */
227     @Override
228     public byte[] downloadCode(String tableName)
229     {
230         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
231         ZipOutputStream zip = new ZipOutputStream(outputStream);
232         generatorCode(tableName, zip);
233         IOUtils.closeQuietly(zip);
234         return outputStream.toByteArray();
235     }
236
237     /**
238      * 生成代码(自定义路径)
239      * 
240      * @param tableName 表名称
241      */
242     @Override
243     public void generatorCode(String tableName)
244     {
245         // 查询表信息
246         GenTable table = genTableMapper.selectGenTableByName(tableName);
247         // 设置主子表信息
248         setSubTable(table);
249         // 设置主键列信息
250         setPkColumn(table);
251
252         VelocityInitializer.initVelocity();
253
254         VelocityContext context = VelocityUtils.prepareContext(table);
255
256         // 获取模板列表
257         List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
258         for (String template : templates)
259         {
260             if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm"))
261             {
262                 // 渲染模板
263                 StringWriter sw = new StringWriter();
264                 Template tpl = Velocity.getTemplate(template, Constants.UTF8);
265                 tpl.merge(context, sw);
266                 try
267                 {
268                     String path = getGenPath(table, template);
269                     FileUtils.writeStringToFile(new File(path), sw.toString(), CharsetKit.UTF_8);
270                 }
271                 catch (IOException e)
272                 {
273                     throw new ServiceException("渲染模板失败,表名:" + table.getTableName());
274                 }
275             }
276         }
277     }
278
279     /**
280      * 同步数据库
281      * 
282      * @param tableName 表名称
283      */
284     @Override
285     @Transactional
286     public void synchDb(String tableName)
287     {
288         GenTable table = genTableMapper.selectGenTableByName(tableName);
289         List<GenTableColumn> tableColumns = table.getColumns();
290         Map<String, GenTableColumn> tableColumnMap = tableColumns.stream().collect(Collectors.toMap(GenTableColumn::getColumnName, Function.identity()));
291
292         List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
293         if (StringUtils.isEmpty(dbTableColumns))
294         {
295             throw new ServiceException("同步数据失败,原表结构不存在");
296         }
297         List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
298
299         dbTableColumns.forEach(column -> {
300             GenUtils.initColumnField(column, table);
301             if (tableColumnMap.containsKey(column.getColumnName()))
302             {
303                 GenTableColumn prevColumn = tableColumnMap.get(column.getColumnName());
304                 column.setColumnId(prevColumn.getColumnId());
305                 if (column.isList())
306                 {
307                     // 如果是列表,继续保留查询方式/字典类型选项
308                     column.setDictType(prevColumn.getDictType());
309                     column.setQueryType(prevColumn.getQueryType());
310                 }
311                 if (StringUtils.isNotEmpty(prevColumn.getIsRequired()) && !column.isPk()
312                         && (column.isInsert() || column.isEdit())
313                         && ((column.isUsableColumn()) || (!column.isSuperColumn())))
314                 {
315                     // 如果是(新增/修改&非主键/非忽略及父属性),继续保留必填/显示类型选项
316                     column.setIsRequired(prevColumn.getIsRequired());
317                     column.setHtmlType(prevColumn.getHtmlType());
318                 }
319                 genTableColumnMapper.updateGenTableColumn(column);
320             }
321             else
322             {
323                 genTableColumnMapper.insertGenTableColumn(column);
324             }
325         });
326
327         List<GenTableColumn> delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList());
328         if (StringUtils.isNotEmpty(delColumns))
329         {
330             genTableColumnMapper.deleteGenTableColumns(delColumns);
331         }
332     }
333
334     /**
335      * 批量生成代码(下载方式)
336      * 
337      * @param tableNames 表数组
338      * @return 数据
339      */
340     @Override
341     public byte[] downloadCode(String[] tableNames)
342     {
343         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
344         ZipOutputStream zip = new ZipOutputStream(outputStream);
345         for (String tableName : tableNames)
346         {
347             generatorCode(tableName, zip);
348         }
349         IOUtils.closeQuietly(zip);
350         return outputStream.toByteArray();
351     }
352
353     /**
354      * 查询表信息并生成代码
355      */
356     private void generatorCode(String tableName, ZipOutputStream zip)
357     {
358         // 查询表信息
359         GenTable table = genTableMapper.selectGenTableByName(tableName);
360         // 设置主子表信息
361         setSubTable(table);
362         // 设置主键列信息
363         setPkColumn(table);
364
365         VelocityInitializer.initVelocity();
366
367         VelocityContext context = VelocityUtils.prepareContext(table);
368
369         // 获取模板列表
370         List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
371         for (String template : templates)
372         {
373             // 渲染模板
374             StringWriter sw = new StringWriter();
375             Template tpl = Velocity.getTemplate(template, Constants.UTF8);
376             tpl.merge(context, sw);
377             try
378             {
379                 // 添加到zip
380                 zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
381                 IOUtils.write(sw.toString(), zip, Constants.UTF8);
382                 IOUtils.closeQuietly(sw);
383                 zip.flush();
384                 zip.closeEntry();
385             }
386             catch (IOException e)
387             {
388                 log.error("渲染模板失败,表名:" + table.getTableName(), e);
389             }
390         }
391     }
392
393     /**
394      * 修改保存参数校验
395      * 
396      * @param genTable 业务信息
397      */
398     @Override
399     public void validateEdit(GenTable genTable)
400     {
401         if (GenConstants.TPL_TREE.equals(genTable.getTplCategory()))
402         {
403             String options = JSON.toJSONString(genTable.getParams());
404             JSONObject paramsObj = JSON.parseObject(options);
405             if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_CODE)))
406             {
407                 throw new ServiceException("树编码字段不能为空");
408             }
409             else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_PARENT_CODE)))
410             {
411                 throw new ServiceException("树父编码字段不能为空");
412             }
413             else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_NAME)))
414             {
415                 throw new ServiceException("树名称字段不能为空");
416             }
417             else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory()))
418             {
419                 if (StringUtils.isEmpty(genTable.getSubTableName()))
420                 {
421                     throw new ServiceException("关联子表的表名不能为空");
422                 }
423                 else if (StringUtils.isEmpty(genTable.getSubTableFkName()))
424                 {
425                     throw new ServiceException("子表关联的外键名不能为空");
426                 }
427             }
428         }
429     }
430
431     /**
432      * 设置主键列信息
433      * 
434      * @param table 业务表信息
435      */
436     public void setPkColumn(GenTable table)
437     {
438         for (GenTableColumn column : table.getColumns())
439         {
440             if (column.isPk())
441             {
442                 table.setPkColumn(column);
443                 break;
444             }
445         }
446         if (StringUtils.isNull(table.getPkColumn()))
447         {
448             table.setPkColumn(table.getColumns().get(0));
449         }
450         if (GenConstants.TPL_SUB.equals(table.getTplCategory()))
451         {
452             for (GenTableColumn column : table.getSubTable().getColumns())
453             {
454                 if (column.isPk())
455                 {
456                     table.getSubTable().setPkColumn(column);
457                     break;
458                 }
459             }
460             if (StringUtils.isNull(table.getSubTable().getPkColumn()))
461             {
462                 table.getSubTable().setPkColumn(table.getSubTable().getColumns().get(0));
463             }
464         }
465     }
466
467     /**
468      * 设置主子表信息
469      * 
470      * @param table 业务表信息
471      */
472     public void setSubTable(GenTable table)
473     {
474         String subTableName = table.getSubTableName();
475         if (StringUtils.isNotEmpty(subTableName))
476         {
477             table.setSubTable(genTableMapper.selectGenTableByName(subTableName));
478         }
479     }
480
481     /**
482      * 设置代码生成其他选项值
483      * 
484      * @param genTable 设置后的生成对象
485      */
486     public void setTableFromOptions(GenTable genTable)
487     {
488         JSONObject paramsObj = JSON.parseObject(genTable.getOptions());
489         if (StringUtils.isNotNull(paramsObj))
490         {
491             String treeCode = paramsObj.getString(GenConstants.TREE_CODE);
492             String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE);
493             String treeName = paramsObj.getString(GenConstants.TREE_NAME);
494             String parentMenuId = paramsObj.getString(GenConstants.PARENT_MENU_ID);
495             String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME);
496
497             genTable.setTreeCode(treeCode);
498             genTable.setTreeParentCode(treeParentCode);
499             genTable.setTreeName(treeName);
500             genTable.setParentMenuId(parentMenuId);
501             genTable.setParentMenuName(parentMenuName);
502         }
503     }
504
505     /**
506      * 获取代码生成地址
507      * 
508      * @param table 业务表信息
509      * @param template 模板文件路径
510      * @return 生成地址
511      */
512     public static String getGenPath(GenTable table, String template)
513     {
514         String genPath = table.getGenPath();
515         if (StringUtils.equals(genPath, "/"))
516         {
517             return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table);
518         }
519         return genPath + File.separator + VelocityUtils.getFileName(template, table);
520     }
521 }