package com.freetmp.mbg.plugin.upsert;
import com.freetmp.mbg.plugin.AbstractXmbgPlugin;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/**
* 存在即更新否则插入方法生成插件
*
* @author Pin Liu
*/
public abstract class AbstractUpsertPlugin extends AbstractXmbgPlugin {
private final Logger log = LoggerFactory.getLogger(AbstractUpsertPlugin.class);
public static final String UPSERT = "upsert";
public static final String UPSERT_SELECTIVE = "upsertSelective";
public static final String IDENTIFIERS_ARRAY_CONDITIONS = "Identifiers_Array_Conditions";
public static final String PROPERTY_PREFIX = "record.";
@Override
public boolean validate(List<String> warnings) {
return true;
}
@Override
public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
/*-----------------------------添加单个upsert的接口方法-----------------------------------*/
Method upsert = new Method(UPSERT);
upsert.setReturnType(FullyQualifiedJavaType.getIntInstance());
Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
FullyQualifiedJavaType parameterType = introspectedTable.getRules().calculateAllFieldsClass();
upsert.addParameter(new Parameter(parameterType, "record", "@Param(\"record\")"));
importedTypes.add(parameterType);
FullyQualifiedJavaType arrayType = new FullyQualifiedJavaType((new String[]{}).getClass().getCanonicalName());
upsert.addParameter(new Parameter(arrayType, "array", "@Param(\"array\")"));
importedTypes.add(arrayType);
importedTypes.add(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Param"));
interfaze.addMethod(upsert);
/*-----------------------------添加单个upsertSelective的接口方法-----------------------------------*/
Method upsertSelective = new Method(UPSERT_SELECTIVE);
upsertSelective.setReturnType(FullyQualifiedJavaType.getIntInstance());
upsertSelective.addParameter(new Parameter(parameterType, "record", "@Param(\"record\")"));
upsertSelective.addParameter(new Parameter(arrayType, "array", "@Param(\"array\")"));
interfaze.addMethod(upsertSelective);
interfaze.addImportedTypes(importedTypes);
return true;
}
@Override
public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
XmlElement sql = buildSqlClause(introspectedTable);
document.getRootElement().addElement(sql);
addSingleUpsertToSqlMap(document, introspectedTable);
addSingleUpsertSelectiveToSqlMap(document, introspectedTable);
return true;
}
/**
* add update xml element to mapper.xml for upsert
*
* @param document The generated xml mapper dom
* @param introspectedTable The metadata for database table
*/
protected void addSingleUpsertToSqlMap(Document document, IntrospectedTable introspectedTable) {
XmlElement update = new XmlElement("update");
update.addAttribute(new Attribute("id", UPSERT));
update.addAttribute(new Attribute("parameterType", "map"));
generateSqlMapContent(introspectedTable, update);
document.getRootElement().addElement(update);
}
protected void addSingleUpsertSelectiveToSqlMap(Document document, IntrospectedTable introspectedTable) {
XmlElement update = new XmlElement("update");
update.addAttribute(new Attribute("id", UPSERT_SELECTIVE));
update.addAttribute(new Attribute("parameterType", "map"));
generateSqlMapContentSelective(introspectedTable, update);
document.getRootElement().addElement(update);
}
/**
* 生成sqlMap里对应的xml元素
*
* @param introspectedTable The metadata for database table
* @param parent The parent element for generated xml element
*/
protected abstract void generateSqlMapContent(IntrospectedTable introspectedTable, XmlElement parent);
protected abstract void generateSqlMapContentSelective(IntrospectedTable introspectedTable, XmlElement parent);
/**
* 生成根据参数array判断where条件的元素
*
* @param introspectedTable The metadata for database table
* @return generated where condition element
*/
protected XmlElement checkArrayWhere(IntrospectedTable introspectedTable) {
XmlElement where = new XmlElement("where");
XmlElement include = new XmlElement("include");
include.addAttribute(new Attribute("refid", IDENTIFIERS_ARRAY_CONDITIONS));
where.addElement(include);
return where;
}
/**
* 创建根据传入的Array数组进行判断的sql语句
*
* @param introspectedTable The metadata for database table
* @return generated xml element for check input array params
*/
protected XmlElement buildSqlClause(IntrospectedTable introspectedTable) {
XmlElement sql = new XmlElement("sql");
sql.addAttribute(new Attribute("id", IDENTIFIERS_ARRAY_CONDITIONS));
XmlElement foreach = new XmlElement("foreach");
foreach.addAttribute(new Attribute("collection", "array"));
foreach.addAttribute(new Attribute("item", "item"));
foreach.addAttribute(new Attribute("index", "index"));
foreach.addAttribute(new Attribute("separator", " and "));
StringBuilder sb = new StringBuilder();
for (IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) {
XmlElement isEqualElement = new XmlElement("if");
sb.setLength(0);
sb.append("item == \'");
sb.append(introspectedColumn.getJavaProperty());
sb.append("\'");
isEqualElement.addAttribute(new Attribute("test", sb.toString()));
foreach.addElement(isEqualElement);
sb.setLength(0);
sb.append(MyBatis3FormattingUtilities.getAliasedEscapedColumnName(introspectedColumn));
sb.append(" = ");
sb.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn, PROPERTY_PREFIX));
isEqualElement.addElement(new TextElement(sb.toString()));
}
sql.addElement(foreach);
return sql;
}
}