diff --git a/src/main/java/com/itfsw/mybatis/generator/plugins/UpsertPlugin.java b/src/main/java/com/itfsw/mybatis/generator/plugins/UpsertPlugin.java index 50a60f8..7055c0b 100644 --- a/src/main/java/com/itfsw/mybatis/generator/plugins/UpsertPlugin.java +++ b/src/main/java/com/itfsw/mybatis/generator/plugins/UpsertPlugin.java @@ -18,17 +18,21 @@ package com.itfsw.mybatis.generator.plugins; import com.itfsw.mybatis.generator.plugins.utils.CommTools; import com.itfsw.mybatis.generator.plugins.utils.CommentTools; +import com.itfsw.mybatis.generator.plugins.utils.XmlElementGeneratorTools; import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.PluginAdapter; import org.mybatis.generator.api.dom.java.*; import org.mybatis.generator.api.dom.xml.*; +import org.mybatis.generator.codegen.mybatis3.ListUtilities; import org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities; import org.mybatis.generator.internal.util.StringUtility; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Iterator; import java.util.List; +import java.util.Properties; /** * --------------------------------------------------------------------------- @@ -42,6 +46,10 @@ public class UpsertPlugin extends PluginAdapter { private static final Logger logger = LoggerFactory.getLogger(BatchInsertPlugin.class); public static final String METHOD_UPSERT = "upsert"; // 方法名 public static final String METHOD_UPSERT_SELECTIVE = "upsertSelective"; // 方法名 + public static final String METHOD_UPSERT_BY_EXAMPLE = "upsertByExample"; // 方法名 + + public static final String PRE_ALLOW_MULTI_QUERIES = "allowMultiQueries"; // property allowMultiQueries + private boolean allowMultiQueries = false; // 是否允许多sql提交 /** * {@inheritDoc} @@ -60,6 +68,15 @@ public class UpsertPlugin extends PluginAdapter { return false; } + // 插件是否开启了多sql提交 + Properties properties = this.getProperties(); + String allowMultiQueries = properties.getProperty(PRE_ALLOW_MULTI_QUERIES); + this.allowMultiQueries = allowMultiQueries == null ? false : StringUtility.isTrue(allowMultiQueries); + if (this.allowMultiQueries){ + // 提示用户注意信息 + logger.warn("itfsw:插件" + this.getClass().getTypeName() + "插件您开启了allowMultiQueries支持,注意在jdbc url 配置中增加“allowMultiQueries=true”支持(不怎么建议使用该功能,开启多sql提交会增加sql注入的风险,请确保你所有sql都使用MyBatis书写,请不要使用statement进行sql提交)!"); + } + return true; } @@ -98,6 +115,21 @@ public class UpsertPlugin extends PluginAdapter { interfaze.addMethod(mUpsertSelective); logger.debug("itfsw(存在即更新插件):" + interfaze.getType().getShortName() + "增加upsertSelective方法。"); + if (this.allowMultiQueries){ + // ====================================== 3. upsertByExample ====================================== + Method mUpsertByExample = new Method(METHOD_UPSERT_BY_EXAMPLE); + // 返回值类型 + mUpsertByExample.setReturnType(null); + // 添加参数 + mUpsertByExample.addParameter(new Parameter(introspectedTable.getRules().calculateAllFieldsClass(), "record", "@Param(\"record\")")); + mUpsertByExample.addParameter(new Parameter(new FullyQualifiedJavaType(introspectedTable.getExampleType()), "example", "@Param(\"example\")")); + // 添加方法说明 + CommentTools.addGeneralMethodComment(mUpsertByExample, introspectedTable); + // interface 增加方法 + interfaze.addMethod(mUpsertByExample); + logger.debug("itfsw(存在即更新插件):" + interfaze.getType().getShortName() + "增加upsertByExample方法。"); + } + return true; } @@ -128,7 +160,9 @@ public class UpsertPlugin extends PluginAdapter { eleUpsert.addElement(new TextElement("insert into " + introspectedTable.getFullyQualifiedTableNameAtRuntime())); eleUpsert.addElement(this.generateInsertClause(introspectedTable)); eleUpsert.addElement(new TextElement("values")); + eleUpsert.addElement(new TextElement("(")); eleUpsert.addElement(this.generateValuesClause(introspectedTable)); + eleUpsert.addElement(new TextElement(")")); eleUpsert.addElement(new TextElement("on duplicate key update ")); eleUpsert.addElement(this.generateDuplicateClause(introspectedTable)); @@ -158,9 +192,71 @@ public class UpsertPlugin extends PluginAdapter { document.getRootElement().addElement(eleUpsertSelective); logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加upsertSelective实现方法。"); + if (this.allowMultiQueries){ + // ====================================== 2. upsertByExample ====================================== + XmlElement eleUpsertByExample = new XmlElement("insert"); + eleUpsertByExample.addAttribute(new Attribute("id", METHOD_UPSERT_BY_EXAMPLE)); + // 参数类型 + eleUpsertByExample.addAttribute(new Attribute("parameterType", "map")); + // 添加注释(!!!必须添加注释,overwrite覆盖生成时,@see XmlFileMergerJaxp.isGeneratedNode会去判断注释中是否存在OLD_ELEMENT_TAGS中的一点,例子:@mbg.generated) + CommentTools.addComment(eleUpsertByExample); + + // 使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。所以只支持MYSQL和SQLServer + CommTools.useGeneratedKeys(eleUpsertByExample, introspectedTable, "record."); + + // insert + eleUpsertByExample.addElement(new TextElement("insert into " + introspectedTable.getFullyQualifiedTableNameAtRuntime())); + eleUpsertByExample.addElement(this.generateInsertClause(introspectedTable)); + this.generateExistsClause(introspectedTable, eleUpsertByExample); + + // multiQueries + eleUpsertByExample.addElement(new TextElement(";")); + + // update + eleUpsertByExample.addElement(new TextElement("update " + introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime())); + eleUpsertByExample.addElement(new TextElement("set")); + Iterator iterator = ListUtilities.removeIdentityAndGeneratedAlwaysColumns(introspectedTable.getAllColumns()).iterator(); + StringBuffer sb = new StringBuffer(); + while (iterator.hasNext()){ + IntrospectedColumn column = iterator.next(); + sb.append(MyBatis3FormattingUtilities.getAliasedEscapedColumnName(column)); + sb.append(" = "); + sb.append(MyBatis3FormattingUtilities.getParameterClause(column, "record.")); + + if (iterator.hasNext()){ + sb.append(","); + } + } + eleUpsertByExample.addElement(new TextElement(sb.toString())); + // update where + eleUpsertByExample.addElement(XmlElementGeneratorTools.getUpdateByExampleIncludeElement(introspectedTable)); + + document.getRootElement().addElement(eleUpsertByExample); + logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加upsertSelective实现方法。"); + } + return true; } + /** + * exists 语句 + * + * @param introspectedTable + * @return + */ + private void generateExistsClause(IntrospectedTable introspectedTable, XmlElement element){ + element.addElement(new TextElement("select")); + element.addElement(this.generateValuesClause(introspectedTable, "record.")); + element.addElement(new TextElement("from dual where not exists")); + element.addElement(new TextElement("(")); + element.addElement(new TextElement("select 1 from " + introspectedTable.getFullyQualifiedTableNameAtRuntime())); + + // if example + element.addElement(XmlElementGeneratorTools.getUpdateByExampleIncludeElement(introspectedTable)); + + element.addElement(new TextElement(")")); + } + /** * 普通insert * @@ -195,22 +291,29 @@ public class UpsertPlugin extends PluginAdapter { * @return */ private Element generateValuesClause(IntrospectedTable introspectedTable){ - StringBuilder valuesClause = new StringBuilder(); + return this.generateValuesClause(introspectedTable, null); + } - valuesClause.append(" ("); + /** + * 普通 values + * + * @param introspectedTable + * @param prefix + * @return + */ + private Element generateValuesClause(IntrospectedTable introspectedTable, String prefix){ + StringBuilder valuesClause = new StringBuilder(); List columns = introspectedTable.getAllColumns(); for (int i = 0; i < columns.size(); i++) { IntrospectedColumn introspectedColumn = columns.get(i); - valuesClause.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn)); + valuesClause.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn, prefix)); if (i + 1 < columns.size()) { valuesClause.append(", "); } } - valuesClause.append(") "); - return new TextElement(valuesClause.toString()); } diff --git a/src/main/java/com/itfsw/mybatis/generator/plugins/utils/CommTools.java b/src/main/java/com/itfsw/mybatis/generator/plugins/utils/CommTools.java index 6b728a8..a2f555c 100644 --- a/src/main/java/com/itfsw/mybatis/generator/plugins/utils/CommTools.java +++ b/src/main/java/com/itfsw/mybatis/generator/plugins/utils/CommTools.java @@ -39,6 +39,17 @@ public class CommTools { * @param introspectedTable */ public static void useGeneratedKeys(XmlElement element, IntrospectedTable introspectedTable){ + useGeneratedKeys(element, introspectedTable, null); + } + + /** + * 使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。所以只支持MYSQL和SQLServer + * + * @param element + * @param introspectedTable + * @param prefix + */ + public static void useGeneratedKeys(XmlElement element, IntrospectedTable introspectedTable, String prefix){ GeneratedKey gk = introspectedTable.getGeneratedKey(); if (gk != null) { IntrospectedColumn introspectedColumn = introspectedTable.getColumn(gk.getColumn()); @@ -47,7 +58,7 @@ public class CommTools { if (introspectedColumn != null) { // 使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。所以只支持MYSQL和SQLServer element.addAttribute(new Attribute("useGeneratedKeys", "true")); //$NON-NLS-1$ //$NON-NLS-2$ - element.addAttribute(new Attribute("keyProperty", introspectedColumn.getJavaProperty())); //$NON-NLS-1$ + element.addAttribute(new Attribute("keyProperty", (prefix == null ? "" : prefix) + introspectedColumn.getJavaProperty())); //$NON-NLS-1$ element.addAttribute(new Attribute("keyColumn", introspectedColumn.getActualColumnName())); //$NON-NLS-1$ } } diff --git a/src/main/java/com/itfsw/mybatis/generator/plugins/utils/CommentTools.java b/src/main/java/com/itfsw/mybatis/generator/plugins/utils/CommentTools.java index 38fe627..75118e1 100644 --- a/src/main/java/com/itfsw/mybatis/generator/plugins/utils/CommentTools.java +++ b/src/main/java/com/itfsw/mybatis/generator/plugins/utils/CommentTools.java @@ -40,17 +40,17 @@ public class CommentTools { */ public static void addFieldComment(Field field, IntrospectedTable introspectedTable) { StringBuilder sb = new StringBuilder(); - field.addJavaDocLine("/**"); //$NON-NLS-1$ - field.addJavaDocLine(" * 这是Mybatis Generator拓展插件生成的属性(请勿删除)."); //$NON-NLS-1$ - sb.append(" * This field corresponds to the database table "); //$NON-NLS-1$ + field.addJavaDocLine("/**"); + field.addJavaDocLine(" * 这是Mybatis Generator拓展插件生成的属性(请勿删除)."); + sb.append(" * This field corresponds to the database table "); sb.append(introspectedTable.getFullyQualifiedTable()); field.addJavaDocLine(sb.toString()); field.addJavaDocLine(" *"); field.addJavaDocLine(" * "+MergeConstants.NEW_ELEMENT_TAG); - field.addJavaDocLine(" * @author hewei"); + field.addJavaDocLine(" * @project https://github.com/itfsw/mybatis-generator-plugin"); - field.addJavaDocLine(" */"); //$NON-NLS-1$ + field.addJavaDocLine(" */"); } /** @@ -61,15 +61,16 @@ public class CommentTools { */ public static void addInnerClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) { StringBuilder sb = new StringBuilder(); - innerClass.addJavaDocLine("/**"); //$NON-NLS-1$ - innerClass.addJavaDocLine(" * 这是Mybatis Generator拓展插件生成的类(请勿删除)."); //$NON-NLS-1$ - sb.append(" * This class corresponds to the database table "); //$NON-NLS-1$ + innerClass.addJavaDocLine("/**"); + innerClass.addJavaDocLine(" * 这是Mybatis Generator拓展插件生成的类(请勿删除)."); + sb.append(" * This class corresponds to the database table "); sb.append(introspectedTable.getFullyQualifiedTable()); innerClass.addJavaDocLine(sb.toString()); innerClass.addJavaDocLine(" *"); innerClass.addJavaDocLine(" * "+MergeConstants.NEW_ELEMENT_TAG); - innerClass.addJavaDocLine(" * @author hewei"); - innerClass.addJavaDocLine(" */"); //$NON-NLS-1$ + innerClass.addJavaDocLine(" * @project https://github.com/itfsw/mybatis-generator-plugin"); + + innerClass.addJavaDocLine(" */"); } /** @@ -80,15 +81,16 @@ public class CommentTools { */ public static void addInnerEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) { StringBuilder sb = new StringBuilder(); - innerEnum.addJavaDocLine("/**"); //$NON-NLS-1$ - innerEnum.addJavaDocLine(" * 这是Mybatis Generator拓展插件生成的枚举(请勿删除)."); //$NON-NLS-1$ - sb.append(" * This class corresponds to the database table "); //$NON-NLS-1$ + innerEnum.addJavaDocLine("/**"); + innerEnum.addJavaDocLine(" * 这是Mybatis Generator拓展插件生成的枚举(请勿删除)."); + sb.append(" * This class corresponds to the database table "); sb.append(introspectedTable.getFullyQualifiedTable()); innerEnum.addJavaDocLine(sb.toString()); innerEnum.addJavaDocLine(" *"); innerEnum.addJavaDocLine(" * "+MergeConstants.NEW_ELEMENT_TAG); - innerEnum.addJavaDocLine(" * @author hewei"); - innerEnum.addJavaDocLine(" */"); //$NON-NLS-1$ + innerEnum.addJavaDocLine(" * @project https://github.com/itfsw/mybatis-generator-plugin"); + + innerEnum.addJavaDocLine(" */"); } /** @@ -99,15 +101,16 @@ public class CommentTools { */ public static void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) { StringBuilder sb = new StringBuilder(); - method.addJavaDocLine("/**"); //$NON-NLS-1$ + method.addJavaDocLine("/**"); method.addJavaDocLine(" * 这是Mybatis Generator拓展插件生成的方法(请勿删除)."); sb.append(" * This method corresponds to the database table "); sb.append(introspectedTable.getFullyQualifiedTable()); method.addJavaDocLine(sb.toString()); method.addJavaDocLine(" *"); method.addJavaDocLine(" * "+MergeConstants.NEW_ELEMENT_TAG); - method.addJavaDocLine(" * @author hewei"); - method.addJavaDocLine(" */"); //$NON-NLS-1$ + method.addJavaDocLine(" * @project https://github.com/itfsw/mybatis-generator-plugin"); + + method.addJavaDocLine(" */"); } /** @@ -117,16 +120,16 @@ public class CommentTools { */ public static void addComment(XmlElement xmlElement) { - xmlElement.addElement(new TextElement("")); //$NON-NLS-1$ + xmlElement.addElement(new TextElement("-->")); } /** @@ -137,15 +140,16 @@ public class CommentTools { */ public static void addInterfaceComment(Interface interf, IntrospectedTable introspectedTable) { StringBuilder sb = new StringBuilder(); - interf.addJavaDocLine("/**"); //$NON-NLS-1$ - interf.addJavaDocLine(" * 这是Mybatis Generator拓展插件生成的接口(请勿删除)."); //$NON-NLS-1$ - sb.append(" * This class corresponds to the database table "); //$NON-NLS-1$ + interf.addJavaDocLine("/**"); + interf.addJavaDocLine(" * 这是Mybatis Generator拓展插件生成的接口(请勿删除)."); + sb.append(" * This class corresponds to the database table "); sb.append(introspectedTable.getFullyQualifiedTable()); interf.addJavaDocLine(sb.toString()); interf.addJavaDocLine(" *"); interf.addJavaDocLine(" * "+MergeConstants.NEW_ELEMENT_TAG); - interf.addJavaDocLine(" * @author hewei"); - interf.addJavaDocLine(" */"); //$NON-NLS-1$ + interf.addJavaDocLine(" * @project https://github.com/itfsw/mybatis-generator-plugin"); + + interf.addJavaDocLine(" */"); } }