From 0732f7916ef2b88d32f38234b007cb5efaa6787d Mon Sep 17 00:00:00 2001 From: Spet Date: Sat, 6 Jul 2019 22:09:00 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E6=A0=B9=E7=9B=AE=E5=BD=95=E4=B8=8B?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0.gitignore=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..153c933 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +HELP.md +/target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +/build/ + +### VS Code ### +.vscode/ -- Gitee From 3ee39b958bf21b589d09a69eaa03add298c9fd7e Mon Sep 17 00:00:00 2001 From: Spet Date: Sat, 6 Jul 2019 22:49:20 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0lombok=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mybatis-enhance-actable/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mybatis-enhance-actable/pom.xml b/mybatis-enhance-actable/pom.xml index e9a547f..43ac8be 100644 --- a/mybatis-enhance-actable/pom.xml +++ b/mybatis-enhance-actable/pom.xml @@ -73,6 +73,12 @@ 1.2 provided + + + org.projectlombok + lombok + 1.18.8 + -- Gitee From 2e762317de954fa781cb9763ffe24b5f78c707a2 Mon Sep 17 00:00:00 2001 From: Spet Date: Sun, 7 Jul 2019 10:36:01 +0800 Subject: [PATCH 3/5] =?UTF-8?q?lombok=E8=AE=BE=E7=BD=AEscope?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mybatis-enhance-actable/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/mybatis-enhance-actable/pom.xml b/mybatis-enhance-actable/pom.xml index 43ac8be..c2d9889 100644 --- a/mybatis-enhance-actable/pom.xml +++ b/mybatis-enhance-actable/pom.xml @@ -78,6 +78,7 @@ org.projectlombok lombok 1.18.8 + provided -- Gitee From d803085fb1eb7cc85fc54876c247ea6bf97d80f3 Mon Sep 17 00:00:00 2001 From: Spet Date: Sun, 7 Jul 2019 12:08:47 +0800 Subject: [PATCH 4/5] =?UTF-8?q?1=E3=80=81=E4=BF=AE=E5=A4=8D=E6=9B=B4?= =?UTF-8?q?=E6=94=B9=E4=B8=BB=E9=94=AE=E5=AD=97=E6=AE=B5=E5=87=BA=E7=8E=B0?= =?UTF-8?q?Multiple=20primary=20key=20defined=E7=9A=84bug=202=E3=80=81?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=95=B0=E6=8D=AE=E8=A1=A8=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=E7=9A=84=E5=A2=9E=E5=88=A0=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mybatis/actable/annotation/Column.java | 27 +- .../actable/command/CreateTableParam.java | 137 +- .../SysMysqlCreateTableManagerImpl.java | 1450 ++++++++--------- .../system/CreateMysqlTablesMapper.xml | 3 + 4 files changed, 751 insertions(+), 866 deletions(-) diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/annotation/Column.java b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/annotation/Column.java index 4a7414c..4f362a2 100644 --- a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/annotation/Column.java +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/annotation/Column.java @@ -10,8 +10,8 @@ import java.lang.annotation.Target; /** * 建表的必备注解 * - * @author sunchenbin - * @version 2016年6月23日 下午6:12:48 + * @author sunchenbin, Spet + * @version 2019/07/06 */ // 该注解用于方法声明 @Target(ElementType.FIELD) @@ -28,55 +28,62 @@ public @interface Column{ * * @return 字段名 */ - public String name(); + String name(); /** * 字段类型 * * @return 字段类型 */ - public String type(); + String type(); /** * 字段长度,默认是255 * * @return 字段长度,默认是255 */ - public int length() default 255; + int length() default 255; /** * 小数点长度,默认是0 * * @return 小数点长度,默认是0 */ - public int decimalLength() default 0; + int decimalLength() default 0; /** * 是否为可以为null,true是可以,false是不可以,默认为true * * @return 是否为可以为null,true是可以,false是不可以,默认为true */ - public boolean isNull() default true; + boolean isNull() default true; /** * 是否是主键,默认false * * @return 是否是主键,默认false */ - public boolean isKey() default false; + boolean isKey() default false; /** * 是否自动递增,默认false 只有主键才能使用 * * @return 是否自动递增,默认false 只有主键才能使用 */ - public boolean isAutoIncrement() default false; + boolean isAutoIncrement() default false; /** * 默认值,默认为null * * @return 默认值,默认为null */ - public String defaultValue() default "NULL"; + String defaultValue() default "NULL"; + + /** + * 数据表字段备注 + * + * @return 默认值,默认为null + */ + String comment() default ""; } diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/command/CreateTableParam.java b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/command/CreateTableParam.java index e591477..763d2c8 100644 --- a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/command/CreateTableParam.java +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/command/CreateTableParam.java @@ -1,14 +1,17 @@ package com.gitee.sunchenbin.mybatis.actable.command; +import lombok.Data; + import java.util.List; /** * 用于存放创建表的字段信息 * - * @author sunchenbin - * @version 2016年6月23日 下午6:11:17 + * @author sunchenbin, Spet + * @version 2019/07/06 */ -public class CreateTableParam{ +@Data +public class CreateTableParam implements Cloneable{ /** * 字段名 @@ -79,120 +82,20 @@ public class CreateTableParam{ * 唯一约束列表 */ private List filedUniqueValue; - - - public String getFieldName(){ - return fieldName; - } - - public void setFieldName(String fieldName){ - this.fieldName = fieldName; - } - - public String getFieldType(){ - return fieldType; - } - - public void setFieldType(String fieldType){ - this.fieldType = fieldType; - } - - public int getFieldLength(){ - return fieldLength; - } - - public void setFieldLength(int fieldLength){ - this.fieldLength = fieldLength; - } - - public int getFieldDecimalLength(){ - return fieldDecimalLength; - } - - public void setFieldDecimalLength(int fieldDecimalLength){ - this.fieldDecimalLength = fieldDecimalLength; - } - - public boolean isFieldIsNull(){ - return fieldIsNull; - } - - public void setFieldIsNull(boolean fieldIsNull){ - this.fieldIsNull = fieldIsNull; - } - - public boolean isFieldIsKey(){ - return fieldIsKey; - } - - public void setFieldIsKey(boolean fieldIsKey){ - this.fieldIsKey = fieldIsKey; - } - - public boolean isFieldIsAutoIncrement(){ - return fieldIsAutoIncrement; - } - - public void setFieldIsAutoIncrement(boolean fieldIsAutoIncrement){ - this.fieldIsAutoIncrement = fieldIsAutoIncrement; - } - public String getFieldDefaultValue(){ - return fieldDefaultValue; - } - - public void setFieldDefaultValue(String fieldDefaultValue){ - this.fieldDefaultValue = fieldDefaultValue; - } - - public int getFileTypeLength(){ - return fileTypeLength; - } - - public void setFileTypeLength(int fileTypeLength){ - this.fileTypeLength = fileTypeLength; - } - - @Deprecated - public boolean isFieldIsUnique(){ - return fieldIsUnique; - } - - @Deprecated - public void setFieldIsUnique(boolean fieldIsUnique){ - this.fieldIsUnique = fieldIsUnique; - } - - public String getFiledIndexName() { - return filedIndexName; - } - - public void setFiledIndexName(String filedIndexName) { - this.filedIndexName = filedIndexName; - } - - public List getFiledIndexValue() { - return filedIndexValue; - } - - public void setFiledIndexValue(List filedIndexValue) { - this.filedIndexValue = filedIndexValue; - } - - public String getFiledUniqueName() { - return filedUniqueName; - } - - public void setFiledUniqueName(String filedUniqueName) { - this.filedUniqueName = filedUniqueName; - } - - public List getFiledUniqueValue() { - return filedUniqueValue; - } - - public void setFiledUniqueValue(List filedUniqueValue) { - this.filedUniqueValue = filedUniqueValue; + /** + * 字段的备注 + */ + private String fieldComment; + + @Override + public CreateTableParam clone() { + CreateTableParam createTableParam = null; + try { + createTableParam = (CreateTableParam) super.clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + return createTableParam; } - } diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/manager/system/SysMysqlCreateTableManagerImpl.java b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/manager/system/SysMysqlCreateTableManagerImpl.java index ed8f0a6..93d83cf 100644 --- a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/manager/system/SysMysqlCreateTableManagerImpl.java +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/manager/system/SysMysqlCreateTableManagerImpl.java @@ -33,748 +33,720 @@ import com.gitee.sunchenbin.mybatis.actable.utils.ClassTools; /** * 项目启动时自动扫描配置的目录中的model,根据配置的规则自动创建或更新表 该逻辑只适用于mysql,其他数据库尚且需要另外扩展,因为sql的语法不同 * - * @author sunchenbin - * @version 2016年6月23日 下午5:58:12 + * @author sunchenbin, Spet + * @version 2019/07/06 */ @Transactional @Service("sysMysqlCreateTableManager") public class SysMysqlCreateTableManagerImpl implements SysMysqlCreateTableManager { - private static final Logger log = LoggerFactory.getLogger(SysMysqlCreateTableManagerImpl.class); - - @Autowired - private CreateMysqlTablesMapper createMysqlTablesMapper; - - @Autowired - private ConfigurationUtil springContextUtil; - - // 获取Mysql的类型,以及类型需要设置几个长度 - private static Map mySqlTypeAndLengthMap = mySqlTypeAndLengthMap(); - - /** - * 要扫描的model所在的pack - */ - private static String pack = null; - - /** - * 自动创建模式:update表示更新,create表示删除原表重新创建 - */ - private static String tableAuto = null; - - /** - * 读取配置文件的三种状态(创建表、更新表、不做任何事情) - */ - public void createMysqlTable() { - // 读取配置信息 - pack = springContextUtil.getConfig(Constants.MODEL_PACK_KEY); - tableAuto = springContextUtil.getConfig(Constants.TABLE_AUTO_KEY); - - // 不做任何事情 - if (!"none".equals(tableAuto) && !"update".equals(tableAuto) && !"create".equals(tableAuto)) { - log.warn("配置mybatis.table.auto错误无法识别,当前配置只支持[none/update/create]三种类型!"); - return; - } - - // 不做任何事情 - if ("none".equals(tableAuto)) { - log.info("配置mybatis.table.auto=none,不需要做任何事情"); - return; - } - - // 从包package中获取所有的Class - Set> classes = ClassTools.getClasses(pack); - - // 初始化用于存储各种操作表结构的容器 - Map>> baseTableMap = initTableMap(); - - // 循环全部的model - for (Class clas : classes) { - - // 没有打注解不需要创建表 - if (null == clas.getAnnotation(Table.class)) { - continue; - } - // 构建出全部表的增删改的map - buildTableMapConstruct(clas, baseTableMap); - } - - // 根据传入的map,分别去创建或修改表结构 - createOrModifyTableConstruct(baseTableMap); - } - - /** - * 初始化用于存储各种操作表结构的容器 - * @return 初始化map - */ - private Map>> initTableMap() { - Map>> baseTableMap = new HashMap>>(); - // 1.用于存需要创建的表名+结构 - baseTableMap.put(Constants.NEW_TABLE_MAP, new HashMap>()); - // 2.用于存需要更新字段类型等的表名+结构 - baseTableMap.put(Constants.MODIFY_TABLE_MAP, new HashMap>()); - // 3.用于存需要增加字段的表名+结构 - baseTableMap.put(Constants.ADD_TABLE_MAP, new HashMap>()); - // 4.用于存需要删除字段的表名+结构 - baseTableMap.put(Constants.REMOVE_TABLE_MAP, new HashMap>()); - // 5.用于存需要删除主键的表名+结构 - baseTableMap.put(Constants.DROPKEY_TABLE_MAP, new HashMap>()); - // 6.用于存需要删除唯一约束的表名+结构 - baseTableMap.put(Constants.DROPINDEXANDUNIQUE_TABLE_MAP, new HashMap>()); - // 7.用于存需要增加的索引 - baseTableMap.put(Constants.ADDINDEX_TABLE_MAP, new HashMap>()); - // 8.用于存需要增加的唯一约束 - baseTableMap.put(Constants.ADDUNIQUE_TABLE_MAP, new HashMap>()); - return baseTableMap; - } - - /** - * 构建出全部表的增删改的map - * - * @param clas - * package中的model的Class - * @param baseTableMap - * 用于存储各种操作表结构的容器 - */ - private void buildTableMapConstruct(Class clas, Map>> baseTableMap) { - - // 获取model的table注解 - Table table = clas.getAnnotation(Table.class); - - // 1. 用于存表的全部字段 - List allFieldList = getAllFields(mySqlTypeAndLengthMap, clas); - if (allFieldList.size() == 0) { - log.warn("扫描model发现" + clas.getName() + "没有建表字段请检查!"); - return; - } - - // 如果配置文件配置的是create,表示将所有的表删掉重新创建 - if ("create".equals(tableAuto)) { - createMysqlTablesMapper.dorpTableByName(table.name()); - } - - // 先查该表是否以存在 - int exist = createMysqlTablesMapper.findTableCountByTableName(table.name()); - - // 不存在时 - if (exist == 0) { - baseTableMap.get(Constants.NEW_TABLE_MAP).put(table.name(), allFieldList); - baseTableMap.get(Constants.ADDINDEX_TABLE_MAP).put(table.name(), getAddIndexList(null, allFieldList)); - baseTableMap.get(Constants.ADDUNIQUE_TABLE_MAP).put(table.name(), getAddUniqueList(null, allFieldList)); - return; - } - - // 已存在时理论上做修改的操作,这里查出该表的结构 - List tableColumnList = createMysqlTablesMapper - .findTableEnsembleByTableName(table.name()); - - // 从sysColumns中取出我们需要比较的列的List - // 先取出name用来筛选出增加和删除的字段 - List columnNames = ClassTools.getPropertyValueList(tableColumnList, - SysMysqlColumns.COLUMN_NAME_KEY); - - // 验证对比从model中解析的allFieldList与从数据库查出来的columnList - // 2. 找出增加的字段 - List addFieldList = getAddFieldList(table, allFieldList, columnNames); - - // 3. 找出删除的字段 - List removeFieldList = getRemoveFieldList(table, columnNames, allFieldList); - - // 4. 找出更新的字段 - List modifyFieldList = getModifyFieldList(table, columnNames,tableColumnList, allFieldList); - - // 5. 找出需要删除主键的字段 - List dropKeyFieldList = getDropKeyFieldList(table, columnNames,tableColumnList, allFieldList); - - // 查询当前表中全部的索引和唯一约束 - Set allIndexAndUniqueNames = createMysqlTablesMapper.findTableIndexByTableName(table.name()); - - // 6. 找出需要删除的索引和唯一约束 - List dropIndexAndUniqueFieldList = getDropIndexAndUniqueList(allIndexAndUniqueNames, allFieldList); - - // 7. 找出需要新增的索引 - List addIndexFieldList = getAddIndexList(allIndexAndUniqueNames, allFieldList); - - // 8. 找出需要新增的唯一约束 - List addUniqueFieldList = getAddUniqueList(allIndexAndUniqueNames, allFieldList); - - if (addFieldList.size() != 0) { - baseTableMap.get(Constants.ADD_TABLE_MAP).put(table.name(), addFieldList); - } - if (removeFieldList.size() != 0) { - baseTableMap.get(Constants.REMOVE_TABLE_MAP).put(table.name(), removeFieldList); - } - if (modifyFieldList.size() != 0) { - baseTableMap.get(Constants.MODIFY_TABLE_MAP).put(table.name(), modifyFieldList); - } - if (dropKeyFieldList.size() != 0) { - baseTableMap.get(Constants.DROPKEY_TABLE_MAP).put(table.name(), dropKeyFieldList); - } - if (dropIndexAndUniqueFieldList.size() != 0) { - baseTableMap.get(Constants.DROPINDEXANDUNIQUE_TABLE_MAP).put(table.name(), dropIndexAndUniqueFieldList); - } - if (addIndexFieldList.size() != 0) { - baseTableMap.get(Constants.ADDINDEX_TABLE_MAP).put(table.name(), addIndexFieldList); - } - if (addUniqueFieldList.size() != 0) { - baseTableMap.get(Constants.ADDUNIQUE_TABLE_MAP).put(table.name(), addUniqueFieldList); - } - } - - /** - * 找出需要新建的索引 - * - * @param allIndexAndUniqueNames - * 当前数据库的索引很约束名 - * @param allFieldList - * model中的所有字段 - * @return 需要新建的索引 - */ - private List getAddIndexList(Set allIndexAndUniqueNames, List allFieldList) { - List addIndexFieldList = new ArrayList(); - if (null == allIndexAndUniqueNames) { - allIndexAndUniqueNames = new HashSet(); - } - for (Object obj : allFieldList) { - CreateTableParam createTableParam = (CreateTableParam) obj; - if (null != createTableParam.getFiledIndexName() && !allIndexAndUniqueNames.contains(createTableParam.getFiledIndexName())) { - addIndexFieldList.add(createTableParam); - } - } - return addIndexFieldList; - } - - /** - * 找出需要新建的唯一约束 - * - * @param allIndexAndUniqueNames - * 当前数据库的索引很约束名 - * @param allFieldList - * model中的所有字段 - * @return 需要新建的唯一约束 - */ - private List getAddUniqueList(Set allIndexAndUniqueNames, List allFieldList) { - List addUniqueFieldList = new ArrayList(); - if (null == allIndexAndUniqueNames) { - allIndexAndUniqueNames = new HashSet(); - } - for (Object obj : allFieldList) { - CreateTableParam createTableParam = (CreateTableParam) obj; - if (null != createTableParam.getFiledUniqueName() && !allIndexAndUniqueNames.contains(createTableParam.getFiledUniqueName())) { - addUniqueFieldList.add(createTableParam); - } - } - return addUniqueFieldList; - } - - /** - * 找出需要删除的索引和唯一约束 - * - * @param allIndexAndUniqueNames - * 当前数据库的索引很约束名 - * @param allFieldList - * model中的所有字段 - * @return 需要删除的索引和唯一约束 - */ - private List getDropIndexAndUniqueList(Set allIndexAndUniqueNames, List allFieldList) { - List dropIndexAndUniqueFieldList = new ArrayList(); - if (null == allIndexAndUniqueNames || allIndexAndUniqueNames.size() == 0) { - return dropIndexAndUniqueFieldList; - } - List currentModelIndexAndUnique = new ArrayList(); - for (Object obj : allFieldList) { - CreateTableParam createTableParam = (CreateTableParam) obj; - if (null != createTableParam.getFiledIndexName()) { - currentModelIndexAndUnique.add(createTableParam.getFiledIndexName()); - } - if (null != createTableParam.getFiledUniqueName()) { - currentModelIndexAndUnique.add(createTableParam.getFiledUniqueName()); - } - } - for (String string : allIndexAndUniqueNames) { - if (!currentModelIndexAndUnique.contains(string)) { - dropIndexAndUniqueFieldList.add(string); - } - } - return dropIndexAndUniqueFieldList; - } - - /** - * 返回需要删除主键的字段 - * - * @param table - * 表 - * @param columnNames - * 数据库中的结构 - * @param tableColumnList - * 表结构 - * @param allFieldList - * model中的所有字段 - * @return 需要删除主键的字段 - */ - private List getDropKeyFieldList(Table table, List columnNames, - List tableColumnList, List allFieldList) { - Map fieldMap = getAllFieldMap(allFieldList); - List dropKeyFieldList = new ArrayList(); - for (SysMysqlColumns sysColumn : tableColumnList) { - // 数据库中有该字段时 - CreateTableParam createTableParam = fieldMap.get(sysColumn.getColumn_name()); - if (createTableParam != null) { - // 原本是主键,现在不是了,那么要去做删除主键的操作 - if ("PRI".equals(sysColumn.getColumn_key()) && !createTableParam.isFieldIsKey()) { - dropKeyFieldList.add(createTableParam); - } - - } - } - return dropKeyFieldList; - } - - /** - * 根据数据库中表的结构和model中表的结构对比找出修改类型默认值等属性的字段 - * - * @param table - * 表 - * @param columnNames - * 数据库中的结构 - * @param tableColumnList - * 表结构 - * @param allFieldList - * model中的所有字段 - * @return 需要修改的字段 - */ - private List getModifyFieldList(Table table, List columnNames, List tableColumnList, - List allFieldList) { - Map fieldMap = getAllFieldMap(allFieldList); - List modifyFieldList = new ArrayList(); - for (SysMysqlColumns sysColumn : tableColumnList) { - // 数据库中有该字段时 - CreateTableParam createTableParam = fieldMap.get(sysColumn.getColumn_name()); - if (createTableParam != null) { - // 验证是否有更新 - // 1.验证类型 - if (!sysColumn.getData_type().toLowerCase().equals(createTableParam.getFieldType().toLowerCase())) { - modifyFieldList.add(createTableParam); - continue; - } - // 2.验证长度 - // 3.验证小数点位数 - int length = (Integer) mySqlTypeAndLengthMap.get(createTableParam.getFieldType().toLowerCase()); - String typeAndLength = createTableParam.getFieldType().toLowerCase(); - if (length == 1) { - // 拼接出类型加长度,比如varchar(1) - typeAndLength = typeAndLength + "(" + createTableParam.getFieldLength() + ")"; - } else if (length == 2) { - // 拼接出类型加长度,比如varchar(1) - typeAndLength = typeAndLength + "(" + createTableParam.getFieldLength() + "," - + createTableParam.getFieldDecimalLength() + ")"; - } - // 判断类型+长度是否相同 - if (!sysColumn.getColumn_type().toLowerCase().equals(typeAndLength)) { - modifyFieldList.add(createTableParam); - continue; - } - - // 4.验证主键 - if (!"PRI".equals(sysColumn.getColumn_key()) && createTableParam.isFieldIsKey()) { - // 原本不是主键,现在变成了主键,那么要去做更新 - modifyFieldList.add(createTableParam); - continue; - } - - // 5.验证自增 - if ("auto_increment".equals(sysColumn.getExtra()) && !createTableParam.isFieldIsAutoIncrement()) { - modifyFieldList.add(createTableParam); - continue; - } - - // 6.验证默认值 - if (sysColumn.getColumn_default() == null || sysColumn.getColumn_default().equals("")) { - // 数据库默认值是null,model中注解设置的默认值不为NULL时,那么需要更新该字段 - if (!"NULL".equals(createTableParam.getFieldDefaultValue())) { - modifyFieldList.add(createTableParam); - continue; - } - } else if (!sysColumn.getColumn_default().equals(createTableParam.getFieldDefaultValue())) { - // 两者不相等时,需要更新该字段 - modifyFieldList.add(createTableParam); - continue; - } - - // 7.验证是否可以为null(主键不参与是否为null的更新) - if (sysColumn.getIs_nullable().equals("NO") && !createTableParam.isFieldIsKey()) { - if (createTableParam.isFieldIsNull()) { - // 一个是可以一个是不可用,所以需要更新该字段 - modifyFieldList.add(createTableParam); - continue; - } - } else if (sysColumn.getIs_nullable().equals("YES") && !createTableParam.isFieldIsKey()) { - if (!createTableParam.isFieldIsNull()) { - // 一个是可以一个是不可用,所以需要更新该字段 - modifyFieldList.add(createTableParam); - continue; - } - } - - } - } - return modifyFieldList; - } - - /** - * 将allFieldList转换为Map结构 - * @param allFieldList - * @return - */ - private Map getAllFieldMap(List allFieldList) { - // 将fieldList转成Map类型,字段名作为主键 - Map fieldMap = new HashMap(); - for (Object obj : allFieldList) { - CreateTableParam createTableParam = (CreateTableParam) obj; - fieldMap.put(createTableParam.getFieldName(), createTableParam); - } - return fieldMap; - } - - /** - * 根据数据库中表的结构和model中表的结构对比找出删除的字段 - * - * @param table - * 表 - * @param columnNames - * 数据库中的结构 - * @param allFieldList - * model中的所有字段 - */ - private List getRemoveFieldList(Table table, List columnNames, List allFieldList) { - Map fieldMap = getAllFieldMap(allFieldList); - // 用于存删除的字段 - List removeFieldList = new ArrayList(); - for (String fieldNm : columnNames) { - // 判断该字段在新的model结构中是否存在 - if (fieldMap.get(fieldNm) == null) { - // 不存在,做删除处理 - removeFieldList.add(fieldNm); - } - } - return removeFieldList; - } - - /** - * 根据数据库中表的结构和model中表的结构对比找出新增的字段 - * - * @param table - * 表 - * @param allFieldList - * model中的所有字段 - * @param columnNames - * 数据库中的结构 - * @return 新增的字段 - */ - private List getAddFieldList(Table table, List allFieldList, List columnNames) { - List addFieldList = new ArrayList(); - for (Object obj : allFieldList) { - CreateTableParam createTableParam = (CreateTableParam) obj; - // 循环新的model中的字段,判断是否在数据库中已经存在 - if (!columnNames.contains(createTableParam.getFieldName())) { - // 不存在,表示要在数据库中增加该字段 - addFieldList.add(obj); - } - } - return addFieldList; - } - - /** - * 迭代出所有model的所有fields - * - * @param mySqlTypeAndLengthMap - * mysql数据类型和对应几个长度的map - * @param clas - * 准备做为创建表依据的class - * @return 表的全部字段 - */ - private List getAllFields(Map mySqlTypeAndLengthMap, Class clas) { - List fieldList = new ArrayList(); - Field[] fields = clas.getDeclaredFields(); - - // 判断是否有父类,如果有拉取父类的field,这里只支持多层继承 - fields = recursionParents(clas, fields); - - for (Field field : fields) { - // 判断方法中是否有指定注解类型的注解 - boolean hasAnnotation = field.isAnnotationPresent(Column.class); - if (hasAnnotation) { - // 根据注解类型返回方法的指定类型注解 - Column column = field.getAnnotation(Column.class); - CreateTableParam param = new CreateTableParam(); - param.setFieldName(column.name()); - param.setFieldType(column.type().toLowerCase()); - param.setFieldLength(column.length()); - param.setFieldDecimalLength(column.decimalLength()); - // 主键时设置必须不为null - if (column.isKey()) { - param.setFieldIsNull(false); - } else { - param.setFieldIsNull(column.isNull()); - } - param.setFieldIsKey(column.isKey()); - param.setFieldIsAutoIncrement(column.isAutoIncrement()); - param.setFieldDefaultValue(column.defaultValue()); - int length = (Integer) mySqlTypeAndLengthMap.get(column.type().toLowerCase()); - param.setFileTypeLength(length); - // 获取当前字段的@Index注解 - Index index = field.getAnnotation(Index.class); - if (null != index) { - param.setFiledIndexName((index.name() == null || index.name().equals("")) ? (Constants.IDX + column.name()) : index.name()); - param.setFiledIndexValue(index.value().length == 0 ? Arrays.asList(column.name()) : Arrays.asList(index.value())); - } - // 获取当前字段的@Unique注解 - Unique unique = field.getAnnotation(Unique.class); - if (null != unique) { - param.setFiledUniqueName((unique.name() == null || unique.name().equals("")) ? (Constants.UNI + column.name()) : unique.name()); - param.setFiledUniqueValue(unique.value().length == 0 ? Arrays.asList(column.name()) : Arrays.asList(unique.value())); - } - fieldList.add(param); - } - } - return fieldList; - } - - /** - * 递归扫描父类的fields - * - * @param clas - * 类 - * @param fields - * 属性 - */ - @SuppressWarnings("rawtypes") - private Field[] recursionParents(Class clas, Field[] fields) { - if (clas.getSuperclass() != null) { - Class clsSup = clas.getSuperclass(); - List fieldList = new ArrayList(); - fieldList.addAll(Arrays.asList(fields)); - fieldList.addAll(Arrays.asList(clsSup.getDeclaredFields())); - fields = new Field[fieldList.size()]; - int i = 0; - for (Object field : fieldList.toArray()) { - fields[i] = (Field) field; - i++; - } - fields = recursionParents(clsSup, fields); - } - return fields; - } - - /** - * 根据传入的map创建或修改表结构 - * - * @param baseTableMap - * 操作sql的数据结构 - */ - private void createOrModifyTableConstruct(Map>> baseTableMap) { - // 1. 创建表 - createTableByMap(baseTableMap.get(Constants.NEW_TABLE_MAP)); - // 2. 删除要变更主键的表的原来的字段的主键 - dropFieldsKeyByMap(baseTableMap.get(Constants.DROPKEY_TABLE_MAP)); - // 3. 添加新的字段 - addFieldsByMap(baseTableMap.get(Constants.ADD_TABLE_MAP)); - // 4. 删除字段 - removeFieldsByMap(baseTableMap.get(Constants.REMOVE_TABLE_MAP)); - // 5. 修改字段类型等 - modifyFieldsByMap(baseTableMap.get(Constants.MODIFY_TABLE_MAP)); - // 6. 删除索引和约束 - dropIndexAndUniqueByMap(baseTableMap.get(Constants.DROPINDEXANDUNIQUE_TABLE_MAP)); - // 7. 创建索引 - addIndexByMap(baseTableMap.get(Constants.ADDINDEX_TABLE_MAP)); - // 8. 创建约束 - addUniqueByMap(baseTableMap.get(Constants.ADDUNIQUE_TABLE_MAP)); - - } - - /** - * 根据map结构删除索引和唯一约束 - * - * @param dropIndexAndUniqueMap - * 用于删除索引和唯一约束 - */ - private void dropIndexAndUniqueByMap(Map> dropIndexAndUniqueMap) { - if (dropIndexAndUniqueMap.size() > 0) { - for (Entry> entry : dropIndexAndUniqueMap.entrySet()) { - for (Object obj : entry.getValue()) { - Map map = new HashMap(); - map.put(entry.getKey(), obj); - log.info("开始删除表" + entry.getKey() + "中的索引" + obj); - createMysqlTablesMapper.dorpTabelIndex(map); - log.info("完成删除表" + entry.getKey() + "中的索引" + obj); - } - } - } - } - - /** - * 根据map结构创建索引 - * - * @param addIndexMap - * 用于创建索引和唯一约束 - */ - private void addIndexByMap(Map> addIndexMap) { - if (addIndexMap.size() > 0) { - for (Entry> entry : addIndexMap.entrySet()) { - for (Object obj : entry.getValue()) { - Map map = new HashMap(); - map.put(entry.getKey(), obj); - CreateTableParam fieldProperties = (CreateTableParam) obj; - if (null != fieldProperties.getFiledIndexName()) { - log.info("开始创建表" + entry.getKey() + "中的索引" + fieldProperties.getFiledIndexName()); - createMysqlTablesMapper.addTableIndex(map); - log.info("完成创建表" + entry.getKey() + "中的索引" + fieldProperties.getFiledIndexName()); - } - } - } - } - } - - /** - * 根据map结构创建唯一约束 - * - * @param addUniqueMap - * 用于创建索引和唯一约束 - */ - private void addUniqueByMap(Map> addUniqueMap) { - if (addUniqueMap.size() > 0) { - for (Entry> entry : addUniqueMap.entrySet()) { - for (Object obj : entry.getValue()) { - Map map = new HashMap(); - map.put(entry.getKey(), obj); - CreateTableParam fieldProperties = (CreateTableParam) obj; - if (null != fieldProperties.getFiledUniqueName()) { - log.info("开始创建表" + entry.getKey() + "中的唯一约束" + fieldProperties.getFiledUniqueName()); - createMysqlTablesMapper.addTableUnique(map); - log.info("完成创建表" + entry.getKey() + "中的唯一约束" + fieldProperties.getFiledUniqueName()); - } - } - } - } - } - - /** - * 根据map结构修改表中的字段类型等 - * - * @param modifyTableMap - * 用于存需要更新字段类型等的表名+结构 - */ - private void modifyFieldsByMap(Map> modifyTableMap) { - // 做修改字段操作 - if (modifyTableMap.size() > 0) { - for (Entry> entry : modifyTableMap.entrySet()) { - for (Object obj : entry.getValue()) { - Map map = new HashMap(); - map.put(entry.getKey(), obj); - CreateTableParam fieldProperties = (CreateTableParam) obj; - log.info("开始修改表" + entry.getKey() + "中的字段" + fieldProperties.getFieldName()); - createMysqlTablesMapper.modifyTableField(map); - log.info("完成修改表" + entry.getKey() + "中的字段" + fieldProperties.getFieldName()); - } - } - } - } - - /** - * 根据map结构删除表中的字段 - * - * @param removeTableMap - * 用于存需要删除字段的表名+结构 - */ - private void removeFieldsByMap(Map> removeTableMap) { - // 做删除字段操作 - if (removeTableMap.size() > 0) { - for (Entry> entry : removeTableMap.entrySet()) { - for (Object obj : entry.getValue()) { - Map map = new HashMap(); - map.put(entry.getKey(), obj); - String fieldName = (String) obj; - log.info("开始删除表" + entry.getKey() + "中的字段" + fieldName); - createMysqlTablesMapper.removeTableField(map); - log.info("完成删除表" + entry.getKey() + "中的字段" + fieldName); - } - } - } - } - - /** - * 根据map结构对表中添加新的字段 - * - * @param addTableMap - * 用于存需要增加字段的表名+结构 - */ - private void addFieldsByMap(Map> addTableMap) { - // 做增加字段操作 - if (addTableMap.size() > 0) { - for (Entry> entry : addTableMap.entrySet()) { - for (Object obj : entry.getValue()) { - Map map = new HashMap(); - map.put(entry.getKey(), obj); - CreateTableParam fieldProperties = (CreateTableParam) obj; - log.info("开始为表" + entry.getKey() + "增加字段" + fieldProperties.getFieldName()); - createMysqlTablesMapper.addTableField(map); - log.info("完成为表" + entry.getKey() + "增加字段" + fieldProperties.getFieldName()); - } - } - } - } - - /** - * 根据map结构删除要变更表中字段的主键 - * - * @param dropKeyTableMap - * 用于存需要删除主键的表名+结构 - */ - private void dropFieldsKeyByMap(Map> dropKeyTableMap) { - // 先去做删除主键的操作,这步操作必须在增加和修改字段之前! - if (dropKeyTableMap.size() > 0) { - for (Entry> entry : dropKeyTableMap.entrySet()) { - for (Object obj : entry.getValue()) { - Map map = new HashMap(); - map.put(entry.getKey(), obj); - CreateTableParam fieldProperties = (CreateTableParam) obj; - log.info("开始为表" + entry.getKey() + "删除主键" + fieldProperties.getFieldName()); - createMysqlTablesMapper.dropKeyTableField(map); - log.info("完成为表" + entry.getKey() + "删除主键" + fieldProperties.getFieldName()); - } - } - } - } - - /** - * 根据map结构创建表 - * - * @param newTableMap - * 用于存需要创建的表名+结构 - */ - private void createTableByMap(Map> newTableMap) { - // 做创建表操作 - if (newTableMap.size() > 0) { - for (Entry> entry : newTableMap.entrySet()) { - Map> map = new HashMap>(); - map.put(entry.getKey(), entry.getValue()); - log.info("开始创建表:" + entry.getKey()); - createMysqlTablesMapper.createTable(map); - log.info("完成创建表:" + entry.getKey()); - } - } - } - - /** - * 获取Mysql的类型,以及类型需要设置几个长度,这里构建成map的样式 - * 构建Map(字段名(小写),需要设置几个长度(0表示不需要设置,1表示需要设置一个,2表示需要设置两个)) - */ - public static Map mySqlTypeAndLengthMap() { - Field[] fields = MySqlTypeConstant.class.getDeclaredFields(); - Map map = new HashMap(); - for (Field field : fields) { - LengthCount lengthCount = field.getAnnotation(LengthCount.class); - map.put(field.getName().toLowerCase(), lengthCount.LengthCount()); - } - return map; - } + private static final Logger log = LoggerFactory.getLogger(SysMysqlCreateTableManagerImpl.class); + + @Autowired + private CreateMysqlTablesMapper createMysqlTablesMapper; + + @Autowired + private ConfigurationUtil springContextUtil; + + // 获取Mysql的类型,以及类型需要设置几个长度 + private static Map mySqlTypeAndLengthMap = mySqlTypeAndLengthMap(); + + /** + * 要扫描的model所在的pack + */ + private static String pack = null; + + /** + * 自动创建模式:update表示更新,create表示删除原表重新创建 + */ + private static String tableAuto = null; + + /** + * 读取配置文件的三种状态(创建表、更新表、不做任何事情) + */ + public void createMysqlTable() { + // 读取配置信息 + pack = springContextUtil.getConfig(Constants.MODEL_PACK_KEY); + tableAuto = springContextUtil.getConfig(Constants.TABLE_AUTO_KEY); + + // 不做任何事情 + if (!"none".equals(tableAuto) && !"update".equals(tableAuto) && !"create".equals(tableAuto)) { + log.warn("配置mybatis.table.auto错误无法识别,当前配置只支持[none/update/create]三种类型!"); + return; + } + + // 不做任何事情 + if ("none".equals(tableAuto)) { + log.info("配置mybatis.table.auto=none,不需要做任何事情"); + return; + } + + // 从包package中获取所有的Class + Set> classes = ClassTools.getClasses(pack); + + // 初始化用于存储各种操作表结构的容器 + Map>> baseTableMap = initTableMap(); + + // 循环全部的model + for (Class clas : classes) { + + // 没有打注解不需要创建表 + if (null == clas.getAnnotation(Table.class)) { + continue; + } + // 构建出全部表的增删改的map + buildTableMapConstruct(clas, baseTableMap); + } + + // 根据传入的map,分别去创建或修改表结构 + createOrModifyTableConstruct(baseTableMap); + } + + /** + * 初始化用于存储各种操作表结构的容器 + * + * @return 初始化map + */ + private Map>> initTableMap() { + Map>> baseTableMap = new HashMap>>(); + // 1.用于存需要创建的表名+结构 + baseTableMap.put(Constants.NEW_TABLE_MAP, new HashMap>()); + // 2.用于存需要更新字段类型等的表名+结构 + baseTableMap.put(Constants.MODIFY_TABLE_MAP, new HashMap>()); + // 3.用于存需要增加字段的表名+结构 + baseTableMap.put(Constants.ADD_TABLE_MAP, new HashMap>()); + // 4.用于存需要删除字段的表名+结构 + baseTableMap.put(Constants.REMOVE_TABLE_MAP, new HashMap>()); + // 5.用于存需要删除主键的表名+结构 + baseTableMap.put(Constants.DROPKEY_TABLE_MAP, new HashMap>()); + // 6.用于存需要删除唯一约束的表名+结构 + baseTableMap.put(Constants.DROPINDEXANDUNIQUE_TABLE_MAP, new HashMap>()); + // 7.用于存需要增加的索引 + baseTableMap.put(Constants.ADDINDEX_TABLE_MAP, new HashMap>()); + // 8.用于存需要增加的唯一约束 + baseTableMap.put(Constants.ADDUNIQUE_TABLE_MAP, new HashMap>()); + return baseTableMap; + } + + /** + * 构建出全部表的增删改的map + * + * @param clas package中的model的Class + * @param baseTableMap 用于存储各种操作表结构的容器 + */ + private void buildTableMapConstruct(Class clas, Map>> baseTableMap) { + + // 获取model的table注解 + Table table = clas.getAnnotation(Table.class); + + // 1. 用于存表的全部字段 + List allFieldList = getAllFields(mySqlTypeAndLengthMap, clas); + if (allFieldList.size() == 0) { + log.warn("扫描model发现" + clas.getName() + "没有建表字段请检查!"); + return; + } + + // 如果配置文件配置的是create,表示将所有的表删掉重新创建 + if ("create".equals(tableAuto)) { + createMysqlTablesMapper.dorpTableByName(table.name()); + } + + // 先查该表是否以存在 + int exist = createMysqlTablesMapper.findTableCountByTableName(table.name()); + + // 不存在时 + if (exist == 0) { + baseTableMap.get(Constants.NEW_TABLE_MAP).put(table.name(), allFieldList); + baseTableMap.get(Constants.ADDINDEX_TABLE_MAP).put(table.name(), getAddIndexList(null, allFieldList)); + baseTableMap.get(Constants.ADDUNIQUE_TABLE_MAP).put(table.name(), getAddUniqueList(null, allFieldList)); + return; + } + + // 已存在时理论上做修改的操作,这里查出该表的结构 + List tableColumnList = createMysqlTablesMapper + .findTableEnsembleByTableName(table.name()); + + // 从sysColumns中取出我们需要比较的列的List + // 先取出name用来筛选出增加和删除的字段 + List columnNames = ClassTools.getPropertyValueList(tableColumnList, + SysMysqlColumns.COLUMN_NAME_KEY); + + // 验证对比从model中解析的allFieldList与从数据库查出来的columnList + // 2. 找出增加的字段 + List addFieldList = getAddFieldList(table, allFieldList, columnNames); + + // 3. 找出删除的字段 + List removeFieldList = getRemoveFieldList(table, columnNames, allFieldList); + + // 4. 找出更新的字段 + List modifyFieldList = getModifyFieldList(table, columnNames, tableColumnList, allFieldList); + + // 5. 找出需要删除主键的字段 + List dropKeyFieldList = getDropKeyFieldList(table, columnNames, tableColumnList, allFieldList); + + // 查询当前表中全部的索引和唯一约束 + Set allIndexAndUniqueNames = createMysqlTablesMapper.findTableIndexByTableName(table.name()); + + // 6. 找出需要删除的索引和唯一约束 + List dropIndexAndUniqueFieldList = getDropIndexAndUniqueList(allIndexAndUniqueNames, allFieldList); + + // 7. 找出需要新增的索引 + List addIndexFieldList = getAddIndexList(allIndexAndUniqueNames, allFieldList); + + // 8. 找出需要新增的唯一约束 + List addUniqueFieldList = getAddUniqueList(allIndexAndUniqueNames, allFieldList); + + if (addFieldList.size() != 0) { + baseTableMap.get(Constants.ADD_TABLE_MAP).put(table.name(), addFieldList); + } + if (removeFieldList.size() != 0) { + baseTableMap.get(Constants.REMOVE_TABLE_MAP).put(table.name(), removeFieldList); + } + if (modifyFieldList.size() != 0) { + baseTableMap.get(Constants.MODIFY_TABLE_MAP).put(table.name(), modifyFieldList); + } + if (dropKeyFieldList.size() != 0) { + baseTableMap.get(Constants.DROPKEY_TABLE_MAP).put(table.name(), dropKeyFieldList); + } + if (dropIndexAndUniqueFieldList.size() != 0) { + baseTableMap.get(Constants.DROPINDEXANDUNIQUE_TABLE_MAP).put(table.name(), dropIndexAndUniqueFieldList); + } + if (addIndexFieldList.size() != 0) { + baseTableMap.get(Constants.ADDINDEX_TABLE_MAP).put(table.name(), addIndexFieldList); + } + if (addUniqueFieldList.size() != 0) { + baseTableMap.get(Constants.ADDUNIQUE_TABLE_MAP).put(table.name(), addUniqueFieldList); + } + } + + /** + * 找出需要新建的索引 + * + * @param allIndexAndUniqueNames 当前数据库的索引很约束名 + * @param allFieldList model中的所有字段 + * @return 需要新建的索引 + */ + private List getAddIndexList(Set allIndexAndUniqueNames, List allFieldList) { + List addIndexFieldList = new ArrayList(); + if (null == allIndexAndUniqueNames) { + allIndexAndUniqueNames = new HashSet(); + } + for (Object obj : allFieldList) { + CreateTableParam createTableParam = (CreateTableParam) obj; + if (null != createTableParam.getFiledIndexName() && !allIndexAndUniqueNames.contains(createTableParam.getFiledIndexName())) { + addIndexFieldList.add(createTableParam); + } + } + return addIndexFieldList; + } + + /** + * 找出需要新建的唯一约束 + * + * @param allIndexAndUniqueNames 当前数据库的索引很约束名 + * @param allFieldList model中的所有字段 + * @return 需要新建的唯一约束 + */ + private List getAddUniqueList(Set allIndexAndUniqueNames, List allFieldList) { + List addUniqueFieldList = new ArrayList(); + if (null == allIndexAndUniqueNames) { + allIndexAndUniqueNames = new HashSet(); + } + for (Object obj : allFieldList) { + CreateTableParam createTableParam = (CreateTableParam) obj; + if (null != createTableParam.getFiledUniqueName() && !allIndexAndUniqueNames.contains(createTableParam.getFiledUniqueName())) { + addUniqueFieldList.add(createTableParam); + } + } + return addUniqueFieldList; + } + + /** + * 找出需要删除的索引和唯一约束 + * + * @param allIndexAndUniqueNames 当前数据库的索引很约束名 + * @param allFieldList model中的所有字段 + * @return 需要删除的索引和唯一约束 + */ + private List getDropIndexAndUniqueList(Set allIndexAndUniqueNames, List allFieldList) { + List dropIndexAndUniqueFieldList = new ArrayList(); + if (null == allIndexAndUniqueNames || allIndexAndUniqueNames.size() == 0) { + return dropIndexAndUniqueFieldList; + } + List currentModelIndexAndUnique = new ArrayList(); + for (Object obj : allFieldList) { + CreateTableParam createTableParam = (CreateTableParam) obj; + if (null != createTableParam.getFiledIndexName()) { + currentModelIndexAndUnique.add(createTableParam.getFiledIndexName()); + } + if (null != createTableParam.getFiledUniqueName()) { + currentModelIndexAndUnique.add(createTableParam.getFiledUniqueName()); + } + } + for (String string : allIndexAndUniqueNames) { + if (!currentModelIndexAndUnique.contains(string)) { + dropIndexAndUniqueFieldList.add(string); + } + } + return dropIndexAndUniqueFieldList; + } + + /** + * 返回需要删除主键的字段 + * + * @param table 表 + * @param columnNames 数据库中的结构 + * @param tableColumnList 表结构 + * @param allFieldList model中的所有字段 + * @return 需要删除主键的字段 + */ + private List getDropKeyFieldList(Table table, List columnNames, + List tableColumnList, List allFieldList) { + Map fieldMap = getAllFieldMap(allFieldList); + List dropKeyFieldList = new ArrayList(); + for (SysMysqlColumns sysColumn : tableColumnList) { + // 数据库中有该字段时 + CreateTableParam createTableParam = fieldMap.get(sysColumn.getColumn_name()); + if (createTableParam != null) { + // 原本是主键,现在不是了,那么要去做删除主键的操作 + if ("PRI".equals(sysColumn.getColumn_key()) && !createTableParam.isFieldIsKey()) { + dropKeyFieldList.add(createTableParam); + } + + } + } + return dropKeyFieldList; + } + + /** + * 根据数据库中表的结构和model中表的结构对比找出修改类型默认值等属性的字段 + * + * @param table 表 + * @param columnNames 数据库中的结构 + * @param tableColumnList 表结构 + * @param allFieldList model中的所有字段 + * @return 需要修改的字段 + */ + private List getModifyFieldList(Table table, List columnNames, List tableColumnList, + List allFieldList) { + Map fieldMap = getAllFieldMap(allFieldList); + List modifyFieldList = new ArrayList(); + for (SysMysqlColumns sysColumn : tableColumnList) { + // 数据库中有该字段时,验证是否有更新 + CreateTableParam createTableParam = fieldMap.get(sysColumn.getColumn_name()); + if (createTableParam != null) { + // 该复制操作时为了解决multiple primary key defined的同时又不会drop primary key + CreateTableParam modifyTableParam = createTableParam.clone(); + // 1.验证主键 + // 原本不是主键,现在变成了主键,那么要去做更新 + if (!"PRI".equals(sysColumn.getColumn_key()) && createTableParam.isFieldIsKey()) { + modifyFieldList.add(modifyTableParam); + continue; + } + // 原本是主键,现在依然主键,坚决不能在alter语句后加primary key,否则会报multiple primary key defined + if("PRI".equals(sysColumn.getColumn_key()) && createTableParam.isFieldIsKey()){ + modifyTableParam.setFieldIsKey(false); + } + // 2.验证类型 + if (!sysColumn.getData_type().toLowerCase().equals(createTableParam.getFieldType().toLowerCase())) { + modifyFieldList.add(modifyTableParam); + continue; + } + // 3.验证长度个小数点位数 + // 4.验证小数点位数 + int length = (Integer) mySqlTypeAndLengthMap.get(createTableParam.getFieldType().toLowerCase()); + String typeAndLength = createTableParam.getFieldType().toLowerCase(); + if (length == 1) { + // 拼接出类型加长度,比如varchar(1) + typeAndLength = typeAndLength + "(" + createTableParam.getFieldLength() + ")"; + } else if (length == 2) { + // 拼接出类型加长度,比如varchar(1) + typeAndLength = typeAndLength + "(" + createTableParam.getFieldLength() + "," + + createTableParam.getFieldDecimalLength() + ")"; + } + // 判断类型+长度是否相同 + if (!sysColumn.getColumn_type().toLowerCase().equals(typeAndLength)) { + modifyFieldList.add(modifyTableParam); + continue; + } + // 5.验证自增 + if ("auto_increment".equals(sysColumn.getExtra()) && !createTableParam.isFieldIsAutoIncrement()) { + modifyFieldList.add(modifyTableParam); + continue; + } + // 6.验证默认值 + if (sysColumn.getColumn_default() == null || sysColumn.getColumn_default().equals("")) { + // 数据库默认值是null,model中注解设置的默认值不为NULL时,那么需要更新该字段 + if (!"NULL".equals(createTableParam.getFieldDefaultValue())) { + modifyFieldList.add(modifyTableParam); + continue; + } + } else if (!sysColumn.getColumn_default().equals(createTableParam.getFieldDefaultValue())) { + // 两者不相等时,需要更新该字段 + modifyFieldList.add(modifyTableParam); + continue; + } + // 7.验证是否可以为null(主键不参与是否为null的更新) + if (sysColumn.getIs_nullable().equals("NO") && !createTableParam.isFieldIsKey()) { + if (createTableParam.isFieldIsNull()) { + // 一个是可以一个是不可用,所以需要更新该字段 + modifyFieldList.add(modifyTableParam); + continue; + } + } else if (sysColumn.getIs_nullable().equals("YES") && !createTableParam.isFieldIsKey()) { + if (!createTableParam.isFieldIsNull()) { + // 一个是可以一个是不可用,所以需要更新该字段 + modifyFieldList.add(modifyTableParam); + continue; + } + } + // 8.验证注释 + if (!sysColumn.getColumn_comment().equals(createTableParam.getFieldComment())) { + modifyFieldList.add(modifyTableParam); + } + } + } + return modifyFieldList; + } + + /** + * 将allFieldList转换为Map结构 + * + * @param allFieldList + * @return + */ + private Map getAllFieldMap(List allFieldList) { + // 将fieldList转成Map类型,字段名作为主键 + Map fieldMap = new HashMap(); + for (Object obj : allFieldList) { + CreateTableParam createTableParam = (CreateTableParam) obj; + fieldMap.put(createTableParam.getFieldName(), createTableParam); + } + return fieldMap; + } + + /** + * 根据数据库中表的结构和model中表的结构对比找出删除的字段 + * + * @param table 表 + * @param columnNames 数据库中的结构 + * @param allFieldList model中的所有字段 + */ + private List getRemoveFieldList(Table table, List columnNames, List allFieldList) { + Map fieldMap = getAllFieldMap(allFieldList); + // 用于存删除的字段 + List removeFieldList = new ArrayList(); + for (String fieldNm : columnNames) { + // 判断该字段在新的model结构中是否存在 + if (fieldMap.get(fieldNm) == null) { + // 不存在,做删除处理 + removeFieldList.add(fieldNm); + } + } + return removeFieldList; + } + + /** + * 根据数据库中表的结构和model中表的结构对比找出新增的字段 + * + * @param table 表 + * @param allFieldList model中的所有字段 + * @param columnNames 数据库中的结构 + * @return 新增的字段 + */ + private List getAddFieldList(Table table, List allFieldList, List columnNames) { + List addFieldList = new ArrayList(); + for (Object obj : allFieldList) { + CreateTableParam createTableParam = (CreateTableParam) obj; + // 循环新的model中的字段,判断是否在数据库中已经存在 + if (!columnNames.contains(createTableParam.getFieldName())) { + // 不存在,表示要在数据库中增加该字段 + addFieldList.add(obj); + } + } + return addFieldList; + } + + /** + * 迭代出所有model的所有fields + * + * @param mySqlTypeAndLengthMap mysql数据类型和对应几个长度的map + * @param clas 准备做为创建表依据的class + * @return 表的全部字段 + */ + private List getAllFields(Map mySqlTypeAndLengthMap, Class clas) { + List fieldList = new ArrayList(); + Field[] fields = clas.getDeclaredFields(); + + // 判断是否有父类,如果有拉取父类的field,这里只支持多层继承 + fields = recursionParents(clas, fields); + + for (Field field : fields) { + // 判断方法中是否有指定注解类型的注解 + boolean hasAnnotation = field.isAnnotationPresent(Column.class); + if (hasAnnotation) { + // 根据注解类型返回方法的指定类型注解 + Column column = field.getAnnotation(Column.class); + CreateTableParam param = new CreateTableParam(); + param.setFieldName(column.name()); + param.setFieldType(column.type().toLowerCase()); + param.setFieldLength(column.length()); + param.setFieldDecimalLength(column.decimalLength()); + // 主键时设置必须不为null + if (column.isKey()) { + param.setFieldIsNull(false); + } else { + param.setFieldIsNull(column.isNull()); + } + param.setFieldIsKey(column.isKey()); + param.setFieldIsAutoIncrement(column.isAutoIncrement()); + param.setFieldDefaultValue(column.defaultValue()); + param.setFieldComment(column.comment()); + int length = (Integer) mySqlTypeAndLengthMap.get(column.type().toLowerCase()); + param.setFileTypeLength(length); + // 获取当前字段的@Index注解 + Index index = field.getAnnotation(Index.class); + if (null != index) { + param.setFiledIndexName((index.name() == null || index.name().equals("")) ? (Constants.IDX + column.name()) : index.name()); + param.setFiledIndexValue(index.value().length == 0 ? Arrays.asList(column.name()) : Arrays.asList(index.value())); + } + // 获取当前字段的@Unique注解 + Unique unique = field.getAnnotation(Unique.class); + if (null != unique) { + param.setFiledUniqueName((unique.name() == null || unique.name().equals("")) ? (Constants.UNI + column.name()) : unique.name()); + param.setFiledUniqueValue(unique.value().length == 0 ? Arrays.asList(column.name()) : Arrays.asList(unique.value())); + } + fieldList.add(param); + } + } + return fieldList; + } + + /** + * 递归扫描父类的fields + * + * @param clas 类 + * @param fields 属性 + */ + @SuppressWarnings("rawtypes") + private Field[] recursionParents(Class clas, Field[] fields) { + if (clas.getSuperclass() != null) { + Class clsSup = clas.getSuperclass(); + List fieldList = new ArrayList(); + fieldList.addAll(Arrays.asList(fields)); + fieldList.addAll(Arrays.asList(clsSup.getDeclaredFields())); + fields = new Field[fieldList.size()]; + int i = 0; + for (Object field : fieldList.toArray()) { + fields[i] = (Field) field; + i++; + } + fields = recursionParents(clsSup, fields); + } + return fields; + } + + /** + * 根据传入的map创建或修改表结构 + * + * @param baseTableMap 操作sql的数据结构 + */ + private void createOrModifyTableConstruct(Map>> baseTableMap) { + // 1. 创建表 + createTableByMap(baseTableMap.get(Constants.NEW_TABLE_MAP)); + // 2. 删除要变更主键的表的原来的字段的主键 + dropFieldsKeyByMap(baseTableMap.get(Constants.DROPKEY_TABLE_MAP)); + // 3. 添加新的字段 + addFieldsByMap(baseTableMap.get(Constants.ADD_TABLE_MAP)); + // 4. 删除字段 + removeFieldsByMap(baseTableMap.get(Constants.REMOVE_TABLE_MAP)); + // 5. 修改字段类型等 + modifyFieldsByMap(baseTableMap.get(Constants.MODIFY_TABLE_MAP)); + // 6. 删除索引和约束 + dropIndexAndUniqueByMap(baseTableMap.get(Constants.DROPINDEXANDUNIQUE_TABLE_MAP)); + // 7. 创建索引 + addIndexByMap(baseTableMap.get(Constants.ADDINDEX_TABLE_MAP)); + // 8. 创建约束 + addUniqueByMap(baseTableMap.get(Constants.ADDUNIQUE_TABLE_MAP)); + + } + + /** + * 根据map结构删除索引和唯一约束 + * + * @param dropIndexAndUniqueMap 用于删除索引和唯一约束 + */ + private void dropIndexAndUniqueByMap(Map> dropIndexAndUniqueMap) { + if (dropIndexAndUniqueMap.size() > 0) { + for (Entry> entry : dropIndexAndUniqueMap.entrySet()) { + for (Object obj : entry.getValue()) { + Map map = new HashMap(); + map.put(entry.getKey(), obj); + log.info("开始删除表" + entry.getKey() + "中的索引" + obj); + createMysqlTablesMapper.dorpTabelIndex(map); + log.info("完成删除表" + entry.getKey() + "中的索引" + obj); + } + } + } + } + + /** + * 根据map结构创建索引 + * + * @param addIndexMap 用于创建索引和唯一约束 + */ + private void addIndexByMap(Map> addIndexMap) { + if (addIndexMap.size() > 0) { + for (Entry> entry : addIndexMap.entrySet()) { + for (Object obj : entry.getValue()) { + Map map = new HashMap(); + map.put(entry.getKey(), obj); + CreateTableParam fieldProperties = (CreateTableParam) obj; + if (null != fieldProperties.getFiledIndexName()) { + log.info("开始创建表" + entry.getKey() + "中的索引" + fieldProperties.getFiledIndexName()); + createMysqlTablesMapper.addTableIndex(map); + log.info("完成创建表" + entry.getKey() + "中的索引" + fieldProperties.getFiledIndexName()); + } + } + } + } + } + + /** + * 根据map结构创建唯一约束 + * + * @param addUniqueMap 用于创建索引和唯一约束 + */ + private void addUniqueByMap(Map> addUniqueMap) { + if (addUniqueMap.size() > 0) { + for (Entry> entry : addUniqueMap.entrySet()) { + for (Object obj : entry.getValue()) { + Map map = new HashMap(); + map.put(entry.getKey(), obj); + CreateTableParam fieldProperties = (CreateTableParam) obj; + if (null != fieldProperties.getFiledUniqueName()) { + log.info("开始创建表" + entry.getKey() + "中的唯一约束" + fieldProperties.getFiledUniqueName()); + createMysqlTablesMapper.addTableUnique(map); + log.info("完成创建表" + entry.getKey() + "中的唯一约束" + fieldProperties.getFiledUniqueName()); + } + } + } + } + } + + /** + * 根据map结构修改表中的字段类型等 + * + * @param modifyTableMap 用于存需要更新字段类型等的表名+结构 + */ + private void modifyFieldsByMap(Map> modifyTableMap) { + // 做修改字段操作 + if (modifyTableMap.size() > 0) { + for (Entry> entry : modifyTableMap.entrySet()) { + for (Object obj : entry.getValue()) { + Map map = new HashMap(); + map.put(entry.getKey(), obj); + CreateTableParam fieldProperties = (CreateTableParam) obj; + log.info("开始修改表" + entry.getKey() + "中的字段" + fieldProperties.getFieldName()); + createMysqlTablesMapper.modifyTableField(map); + log.info("完成修改表" + entry.getKey() + "中的字段" + fieldProperties.getFieldName()); + } + } + } + } + + /** + * 根据map结构删除表中的字段 + * + * @param removeTableMap 用于存需要删除字段的表名+结构 + */ + private void removeFieldsByMap(Map> removeTableMap) { + // 做删除字段操作 + if (removeTableMap.size() > 0) { + for (Entry> entry : removeTableMap.entrySet()) { + for (Object obj : entry.getValue()) { + Map map = new HashMap(); + map.put(entry.getKey(), obj); + String fieldName = (String) obj; + log.info("开始删除表" + entry.getKey() + "中的字段" + fieldName); + createMysqlTablesMapper.removeTableField(map); + log.info("完成删除表" + entry.getKey() + "中的字段" + fieldName); + } + } + } + } + + /** + * 根据map结构对表中添加新的字段 + * + * @param addTableMap 用于存需要增加字段的表名+结构 + */ + private void addFieldsByMap(Map> addTableMap) { + // 做增加字段操作 + if (addTableMap.size() > 0) { + for (Entry> entry : addTableMap.entrySet()) { + for (Object obj : entry.getValue()) { + Map map = new HashMap(); + map.put(entry.getKey(), obj); + CreateTableParam fieldProperties = (CreateTableParam) obj; + log.info("开始为表" + entry.getKey() + "增加字段" + fieldProperties.getFieldName()); + createMysqlTablesMapper.addTableField(map); + log.info("完成为表" + entry.getKey() + "增加字段" + fieldProperties.getFieldName()); + } + } + } + } + + /** + * 根据map结构删除要变更表中字段的主键 + * + * @param dropKeyTableMap 用于存需要删除主键的表名+结构 + */ + private void dropFieldsKeyByMap(Map> dropKeyTableMap) { + // 先去做删除主键的操作,这步操作必须在增加和修改字段之前! + if (dropKeyTableMap.size() > 0) { + for (Entry> entry : dropKeyTableMap.entrySet()) { + for (Object obj : entry.getValue()) { + Map map = new HashMap(); + map.put(entry.getKey(), obj); + CreateTableParam fieldProperties = (CreateTableParam) obj; + log.info("开始为表" + entry.getKey() + "删除主键" + fieldProperties.getFieldName()); + createMysqlTablesMapper.dropKeyTableField(map); + log.info("完成为表" + entry.getKey() + "删除主键" + fieldProperties.getFieldName()); + } + } + } + } + + /** + * 根据map结构创建表 + * + * @param newTableMap 用于存需要创建的表名+结构 + */ + private void createTableByMap(Map> newTableMap) { + // 做创建表操作 + if (newTableMap.size() > 0) { + for (Entry> entry : newTableMap.entrySet()) { + Map> map = new HashMap>(); + map.put(entry.getKey(), entry.getValue()); + log.info("开始创建表:" + entry.getKey()); + createMysqlTablesMapper.createTable(map); + log.info("完成创建表:" + entry.getKey()); + } + } + } + + /** + * 获取Mysql的类型,以及类型需要设置几个长度,这里构建成map的样式 + * 构建Map(字段名(小写),需要设置几个长度(0表示不需要设置,1表示需要设置一个,2表示需要设置两个)) + */ + public static Map mySqlTypeAndLengthMap() { + Field[] fields = MySqlTypeConstant.class.getDeclaredFields(); + Map map = new HashMap(); + for (Field field : fields) { + LengthCount lengthCount = field.getAnnotation(LengthCount.class); + map.put(field.getName().toLowerCase(), lengthCount.LengthCount()); + } + return map; + } } diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/mapping/system/CreateMysqlTablesMapper.xml b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/mapping/system/CreateMysqlTablesMapper.xml index 160af77..35f7583 100644 --- a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/mapping/system/CreateMysqlTablesMapper.xml +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/mapping/system/CreateMysqlTablesMapper.xml @@ -55,6 +55,9 @@ DEFAULT #{fields.fieldDefaultValue} + + COMMENT #{fields.fieldComment} + -- Gitee From 063021e9cb3d1bd501af6a8020f2a5d3086daa02 Mon Sep 17 00:00:00 2001 From: Spet Date: Sun, 7 Jul 2019 12:41:49 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E5=AD=97=E6=AE=B5=E5=A4=87=E6=B3=A8?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E4=B8=BA=E7=A9=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/gitee/sunchenbin/mybatis/actable/annotation/Column.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/annotation/Column.java b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/annotation/Column.java index 4f362a2..9c8bba2 100644 --- a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/annotation/Column.java +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/annotation/Column.java @@ -82,7 +82,7 @@ public @interface Column{ /** * 数据表字段备注 * - * @return 默认值,默认为null + * @return 默认值,默认为空 */ String comment() default ""; -- Gitee