Commit 571ba826 authored by hewei's avatar hewei

fixed:[issues#2]

增加存在即更新插件
parent 9d0068df
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
* 批量插入插件(BatchInsertPlugin) * 批量插入插件(BatchInsertPlugin)
* 逻辑删除插件(LogicalDeletePlugin) * 逻辑删除插件(LogicalDeletePlugin)
* 数据Model属性对应Column获取插件(ModelColumnPlugin) * 数据Model属性对应Column获取插件(ModelColumnPlugin)
* 存在即更新插件(UpsertPlugin)
--------------------------------------- ---------------------------------------
Maven引用: Maven引用:
...@@ -19,7 +20,7 @@ Maven引用: ...@@ -19,7 +20,7 @@ Maven引用:
<dependency> <dependency>
<groupId>com.itfsw</groupId> <groupId>com.itfsw</groupId>
<artifactId>mybatis-generator-plugin</artifactId> <artifactId>mybatis-generator-plugin</artifactId>
<version>1.0.5</version> <version>1.0.6</version>
</dependency> </dependency>
``` ```
--------------------------------------- ---------------------------------------
...@@ -400,4 +401,38 @@ public class Test { ...@@ -400,4 +401,38 @@ public class Test {
this.tbMapper.batchInsertSelective(list, Tb.Column.field1, Tb.Column.field2, Tb.Column.field3, Tb.Column.createTime); this.tbMapper.batchInsertSelective(list, Tb.Column.field1, Tb.Column.field2, Tb.Column.field3, Tb.Column.createTime);
} }
} }
```
### 9. 存在即更新插件
使用MySQL的[“insert ... on duplicate key update”](https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html)实现存在即更新操作,简化数据入库操作([[issues#2]](https://github.com/itfsw/mybatis-generator-plugin/issues/2))。
插件:
```xml
<!-- 存在即更新插件 -->
<plugin type="com.itfsw.mybatis.generator.plugins.UpsertPlugin"/>
```
使用:
```java
public class Test {
public static void main(String[] args) {
// 1. 未入库数据入库,执行insert
Tb tb = new Tb.Builder()
.field1(1)
.field2("xx0")
.delFlag((short)0)
.build();
int k0 = this.tbMapper.upsert(tb);
// 2. 已入库数据再次入库,执行update(!!需要注意如触发update其返回的受影响行数为2)
tb.setField2("xx1");
int k1 = this.tbMapper.upsert(tb);
// 3. 类似insertSelective实现选择入库
Tb tb1 = new Tb.Builder()
.field1(1)
.field2("xx0")
.build();
int k2 = this.tbMapper.upsertSelective(tb1);
tb1.setField2("xx1");
int k3 = this.tbMapper.upsertSelective(tb1);
}
}
``` ```
\ No newline at end of file
/*
* Copyright (c) 2017.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.itfsw.mybatis.generator.plugins;
import com.itfsw.mybatis.generator.plugins.utils.CommTools;
import com.itfsw.mybatis.generator.plugins.utils.CommentTools;
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.MyBatis3FormattingUtilities;
import org.mybatis.generator.internal.util.StringUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
/**
* ---------------------------------------------------------------------------
* 存在即更新插件
* ---------------------------------------------------------------------------
* @author: hewei
* @time:2017/3/21 10:59
* ---------------------------------------------------------------------------
*/
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"; // 方法名
/**
* {@inheritDoc}
*/
@Override
public boolean validate(List<String> warnings) {
// 插件使用前提是targetRuntime为MyBatis3
if (StringUtility.stringHasValue(getContext().getTargetRuntime()) && "MyBatis3".equalsIgnoreCase(getContext().getTargetRuntime()) == false) {
logger.warn("itfsw:插件" + this.getClass().getTypeName() + "要求运行targetRuntime必须为MyBatis3!");
return false;
}
// 插件使用前提是数据库为MySQL
if ("com.mysql.jdbc.Driver".equalsIgnoreCase(this.getContext().getJdbcConnectionConfiguration().getDriverClass()) == false){
logger.warn("itfsw:插件" + this.getClass().getTypeName() + "插件使用前提是数据库为MySQL!");
return false;
}
return true;
}
/**
* Java Client Methods 生成
* 具体执行顺序 http://www.mybatis.org/generator/reference/pluggingIn.html
*
* @param interfaze
* @param topLevelClass
* @param introspectedTable
* @return
*/
@Override
public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
// ====================================== 1. upsert ======================================
Method mUpsert = new Method(METHOD_UPSERT);
// 返回值类型
mUpsert.setReturnType(FullyQualifiedJavaType.getIntInstance());
// 添加参数
mUpsert.addParameter(new Parameter(introspectedTable.getRules().calculateAllFieldsClass(), "record"));
// 添加方法说明
CommentTools.addGeneralMethodComment(mUpsert, introspectedTable);
// interface 增加方法
interfaze.addMethod(mUpsert);
logger.debug("itfsw(存在即更新插件):" + interfaze.getType().getShortName() + "增加upsert方法。");
// ====================================== 2. upsertSelective ======================================
Method mUpsertSelective = new Method(METHOD_UPSERT_SELECTIVE);
// 返回值类型
mUpsertSelective.setReturnType(FullyQualifiedJavaType.getIntInstance());
// 添加参数
mUpsertSelective.addParameter(new Parameter(introspectedTable.getRules().calculateAllFieldsClass(), "record"));
// 添加方法说明
CommentTools.addGeneralMethodComment(mUpsertSelective, introspectedTable);
// interface 增加方法
interfaze.addMethod(mUpsertSelective);
logger.debug("itfsw(存在即更新插件):" + interfaze.getType().getShortName() + "增加upsertSelective方法。");
return true;
}
/**
* SQL Map Methods 生成
* 具体执行顺序 http://www.mybatis.org/generator/reference/pluggingIn.html
*
* @param document
* @param introspectedTable
* @return
*/
@Override
public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
// ====================================== 1. upsert ======================================
XmlElement eleUpsert = new XmlElement("insert");
eleUpsert.addAttribute(new Attribute("id", METHOD_UPSERT));
// 添加注释(!!!必须添加注释,overwrite覆盖生成时,@see XmlFileMergerJaxp.isGeneratedNode会去判断注释中是否存在OLD_ELEMENT_TAGS中的一点,例子:@mbg.generated)
CommentTools.addComment(eleUpsert);
// 参数类型
eleUpsert.addAttribute(new Attribute("parameterType", introspectedTable.getRules().calculateAllFieldsClass().getFullyQualifiedName()));
// 使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。所以只支持MYSQL和SQLServer
CommTools.useGeneratedKeys(eleUpsert, introspectedTable);
// insert
eleUpsert.addElement(new TextElement("insert into " + introspectedTable.getFullyQualifiedTableNameAtRuntime()));
eleUpsert.addElement(this.generateInsertClause(introspectedTable));
eleUpsert.addElement(new TextElement("values"));
eleUpsert.addElement(this.generateValuesClause(introspectedTable));
eleUpsert.addElement(new TextElement("on duplicate key update "));
eleUpsert.addElement(this.generateDuplicateClause(introspectedTable));
document.getRootElement().addElement(eleUpsert);
logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加upsert实现方法。");
// ====================================== 2. upsertSelective ======================================
XmlElement eleUpsertSelective = new XmlElement("insert");
eleUpsertSelective.addAttribute(new Attribute("id", METHOD_UPSERT_SELECTIVE));
// 添加注释(!!!必须添加注释,overwrite覆盖生成时,@see XmlFileMergerJaxp.isGeneratedNode会去判断注释中是否存在OLD_ELEMENT_TAGS中的一点,例子:@mbg.generated)
CommentTools.addComment(eleUpsertSelective);
// 参数类型
eleUpsertSelective.addAttribute(new Attribute("parameterType", introspectedTable.getRules().calculateAllFieldsClass().getFullyQualifiedName()));
// 使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。所以只支持MYSQL和SQLServer
CommTools.useGeneratedKeys(eleUpsertSelective, introspectedTable);
// insert
eleUpsertSelective.addElement(new TextElement("insert into " + introspectedTable.getFullyQualifiedTableNameAtRuntime()));
eleUpsertSelective.addElement(this.generateInsertSelectiveClause(introspectedTable));
eleUpsertSelective.addElement(new TextElement("values"));
eleUpsertSelective.addElement(this.generateValuesSelectiveClause(introspectedTable));
eleUpsertSelective.addElement(new TextElement("on duplicate key update "));
eleUpsertSelective.addElement(this.generateDuplicateSelectiveClause(introspectedTable));
document.getRootElement().addElement(eleUpsertSelective);
logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加upsertSelective实现方法。");
return true;
}
/**
* 普通insert
*
* @param introspectedTable
* @return
*/
private Element generateInsertClause(IntrospectedTable introspectedTable){
StringBuilder insertClause = new StringBuilder();
insertClause.append(" (");
List<IntrospectedColumn> columns = introspectedTable.getAllColumns();
for (int i = 0; i < columns.size(); i++) {
IntrospectedColumn introspectedColumn = columns.get(i);
insertClause.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
if (i + 1 < columns.size()) {
insertClause.append(", ");
}
}
insertClause.append(") ");
return new TextElement(insertClause.toString());
}
/**
* 普通 values
*
* @param introspectedTable
* @return
*/
private Element generateValuesClause(IntrospectedTable introspectedTable){
StringBuilder valuesClause = new StringBuilder();
valuesClause.append(" (");
List<IntrospectedColumn> columns = introspectedTable.getAllColumns();
for (int i = 0; i < columns.size(); i++) {
IntrospectedColumn introspectedColumn = columns.get(i);
valuesClause.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn));
if (i + 1 < columns.size()) {
valuesClause.append(", ");
}
}
valuesClause.append(") ");
return new TextElement(valuesClause.toString());
}
/**
* 普通duplicate
*
* @param introspectedTable
* @return
*/
private Element generateDuplicateClause(IntrospectedTable introspectedTable){
StringBuilder duplicateClause = new StringBuilder();
List<IntrospectedColumn> columns = introspectedTable.getAllColumns();
for (int i = 0; i < columns.size(); i++) {
IntrospectedColumn introspectedColumn = columns.get(i);
duplicateClause.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
duplicateClause.append(" = ");
duplicateClause.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn));
if (i + 1 < columns.size()) {
duplicateClause.append(", ");
}
}
return new TextElement(duplicateClause.toString());
}
/**
* 普通insert
*
* @param introspectedTable
* @return
*/
private Element generateInsertSelectiveClause(IntrospectedTable introspectedTable){
XmlElement insertTrimEle = new XmlElement("trim");
insertTrimEle.addAttribute(new Attribute("prefix", "("));
insertTrimEle.addAttribute(new Attribute("suffix", ")"));
insertTrimEle.addAttribute(new Attribute("suffixOverrides", ","));
StringBuffer sb = new StringBuffer();
for (IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) {
XmlElement insertNotNullElement = new XmlElement("if"); //$NON-NLS-1$
sb.setLength(0);
sb.append(introspectedColumn.getJavaProperty());
sb.append(" != null");
insertNotNullElement.addAttribute(new Attribute("test", sb.toString()));
sb.setLength(0);
sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
sb.append(',');
insertNotNullElement.addElement(new TextElement(sb.toString()));
insertTrimEle.addElement(insertNotNullElement);
}
return insertTrimEle;
}
/**
* 普通 values
*
* @param introspectedTable
* @return
*/
private Element generateValuesSelectiveClause(IntrospectedTable introspectedTable){
XmlElement valuesTrimEle = new XmlElement("trim");
valuesTrimEle.addAttribute(new Attribute("prefix", "("));
valuesTrimEle.addAttribute(new Attribute("suffix", ")"));
valuesTrimEle.addAttribute(new Attribute("suffixOverrides", ","));
StringBuffer sb = new StringBuffer();
for (IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) {
XmlElement valuesNotNullElement = new XmlElement("if"); //$NON-NLS-1$
sb.setLength(0);
sb.append(introspectedColumn.getJavaProperty());
sb.append(" != null");
valuesNotNullElement.addAttribute(new Attribute("test", sb.toString()));
sb.setLength(0);
sb.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn));
sb.append(',');
valuesNotNullElement.addElement(new TextElement(sb.toString()));
valuesTrimEle.addElement(valuesNotNullElement);
}
return valuesTrimEle;
}
/**
* 普通duplicate
*
* @param introspectedTable
* @return
*/
private Element generateDuplicateSelectiveClause(IntrospectedTable introspectedTable){
XmlElement duplicateTrimEle = new XmlElement("trim");
duplicateTrimEle.addAttribute(new Attribute("suffixOverrides", ","));
StringBuffer sb = new StringBuffer();
for (IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) {
XmlElement duplicateNotNullElement = new XmlElement("if"); //$NON-NLS-1$
sb.setLength(0);
sb.append(introspectedColumn.getJavaProperty());
sb.append(" != null");
duplicateNotNullElement.addAttribute(new Attribute("test", sb.toString()));
sb.setLength(0);
sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
sb.append(" = ");
sb.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn));
sb.append(",");
duplicateNotNullElement.addElement(new TextElement(sb.toString()));
duplicateTrimEle.addElement(duplicateNotNullElement);
}
return duplicateTrimEle;
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment