Mybatis生成器插件扩展,生成findInSet方法
public Criteria andNameFindInSet(String value) {addCriterionPattern("find_in_set($value, `name`)", value, "name");return (Criteria) this;}public Criteria andNamePattern(String pattern, String value) {addCriterionPattern(pattern.replace("##column##", "`name`"), value, "name");return (Criteria) this;}
一、生成模式原理
(1)Example.Criterion添加pattern字段
public static class Criterion {private String condition;private Object value;private Object secondValue;private boolean noValue;private boolean singleValue;private boolean betweenValue;private boolean listValue;private String typeHandler;private boolean pattern;
}
(2)Example.GeneratedCriteria加方法addCriterionPattern
protected abstract static class GeneratedCriteriaprotected void addCriterionPattern(String condition, Object value, String property) {if (value == null) {throw new RuntimeException("Value for " + property + " cannot be null");}Criterion c = new Criterion(condition, value);c.setPattern(true);criteria.add(c);}
}
(3) 加对应列FindInSet方法
protected abstract static class GeneratedCriteria {public Criteria andXXXFindInSet(String value) {addCriterionPattern("find_in_set(##value##, `xxx`)", value, "xxx");return (Criteria) this;}
}
(4)改造XXXSqlProvider.applyWhere的 if (criterion.isNoValue()) 前增加模式代码
if (criterion.isPattern()) {String value;if (criterion.getTypeHandler() == null) {value = String.format(parmPhrase1, "", i, j).trim();} else {value = String.format(parmPhrase1_th, "", i, j, criterion.getTypeHandler()).trim();}sb.append(criterion.getCondition().replaceAll("##value##", value));
} else if (criterion.isNoValue()) {sb.append(criterion.getCondition());
} else if (criterion.isSingleValue()) {}
(5)改造XXXMapper.xml的<when test="criterion.noValue">前增加模式代码
<when test="criterion.pattern">and<foreach collection="criterion.condition.split('##value##')" item="criterionCond" separator="#{criterion.value}">${criterionCond}</foreach>
</when>
<when test="criterion.noValue">and ${criterion.condition}
</when>
二、插件代码
package com.mk.mybatisgenerator.plugins;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.Attribute;
import org.mybatis.generator.api.dom.xml.Element;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.codegen.ibatis2.Ibatis2FormattingUtilities;
import java.util.ArrayList;
import java.util.List;public class MySQLMethodPlugin extends PluginAdapter {private final String valueName = "##value##";//值占位符private final String columnName = "##column##";//列名占位符public MySQLMethodPlugin() {super();}@Overridepublic boolean validate(List<String> warnings) {return true;}/*** 重写example* @param topLevelClass* @param introspectedTable* @return*/@Overridepublic boolean modelExampleClassGenerated(TopLevelClass topLevelClass,IntrospectedTable introspectedTable) {addCriterionPattern(topLevelClass, introspectedTable);//增加模式匹配addFindInSet(topLevelClass, introspectedTable);//增加find_in_set方法addPattern(topLevelClass, introspectedTable);//增加模式方法return true;}/*** xml ExampleWhere重写* @param element* @param introspectedTable* @return*/@Overridepublic boolean sqlMapExampleWhereClauseElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {XmlElement whereElement = (XmlElement) element.getElements().get(0);XmlElement foreachElement = (XmlElement) whereElement.getElements().get(0);XmlElement ifElement = (XmlElement) foreachElement.getElements().get(0);XmlElement trimElement = (XmlElement) ifElement.getElements().get(0);XmlElement foreachCriteriaElement = (XmlElement) trimElement.getElements().get(0);XmlElement chooseElement = (XmlElement) foreachCriteriaElement.getElements().get(0);for (Element ele : chooseElement.getElements()) {XmlElement noValueElement = (XmlElement) ele;for (Attribute attribute : noValueElement.getAttributes()) {//找到criterion.noValue行插入模式代码if (attribute.getName().equals("test") && attribute.getValue().equals("criterion.noValue")) {XmlElement patternElement = new XmlElement("when");patternElement.addAttribute(new Attribute("test", "criterion.pattern"));//<foreach collection="oredCriteria" item="criteria" separator="or">XmlElement forElement = new XmlElement("foreach");forElement.addAttribute(new Attribute("collection", "criterion.condition.split('" + valueName + "')"));forElement.addAttribute(new Attribute("item", "criterionCond"));forElement.addAttribute(new Attribute("separator", "#{criterion.value}"));forElement.addElement(new TextElement("${criterionCond}"));patternElement.addElement(new TextElement("and"));patternElement.addElement(forElement);chooseElement.addElement(0, patternElement);return true;}}}throw new RuntimeException("ChooseElement not exist");}/*** 重写ApplyWhere方法* @param method* @param topLevelClass* @param introspectedTable* @return*/@Overridepublic boolean providerApplyWhereMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {List<String> lines = method.getBodyLines();for (int i = 0, len = lines.size(); i < len; i++) {String line = lines.get(i).trim();//找到criterion.noValue行插入模式代码if (line.matches("if\\s*\\(criterion\\.isNoValue\\(\\)\\)\\s*\\{")) {lines.remove(i);List<String> appends = new ArrayList<>();appends.add("if (criterion.isPattern()) {");appends.add("String value;");appends.add(" if (criterion.getTypeHandler() == null) {");appends.add("value = String.format(parmPhrase1, \"\", i, j).trim();");appends.add("} else {");appends.add("value = String.format(parmPhrase1_th, \"\", i, j, criterion.getTypeHandler()).trim();");appends.add("}");appends.add("sb.append(criterion.getCondition().replaceAll(\"" + valueName + "\", value));");appends.add("} else " + line);method.addBodyLines(i, appends);return true;}}throw new RuntimeException("criterion.isNoValue() not exist");}/*protected void addCriterionPattern(String condition, Object value, String property) {if (value == null) {throw new RuntimeException("Value for " + property + " cannot be null");}Criterion c = new Criterion(condition, value);c.setPattern(true);criteria.add(c);}*/public void addCriterionPattern(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {addCriterionPatternField(topLevelClass, introspectedTable);InnerClass criteria = null;// first, find the Criteria inner classfor (InnerClass innerClass : topLevelClass.getInnerClasses()) {if ("GeneratedCriteria".equals(innerClass.getType().getShortName())) { //$NON-NLS-1$criteria = innerClass;break;}}if (criteria == null) {throw new RuntimeException("GeneratedCriteria not exist");}Method method = new Method();method.setVisibility(JavaVisibility.PROTECTED);method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition"));method.addParameter(new Parameter(FullyQualifiedJavaType.getObjectInstance(), "value"));method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "property"));method.setName("addCriterionPattern");method.addBodyLine("if (value == null) {");method.addBodyLine("throw new RuntimeException(\"Value for \" + property + \" cannot be null\");");method.addBodyLine("}");method.addBodyLine("Criterion c = new Criterion(condition, value);");method.addBodyLine("c.setPattern(true);");method.addBodyLine("criteria.add(c);");criteria.addMethod(method);}public void addCriterionPatternField(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {InnerClass criterion = null;// first, find the Criteria inner classfor (InnerClass innerClass : topLevelClass.getInnerClasses()) {if ("Criterion".equals(innerClass.getType().getShortName())) { //$NON-NLS-1$criterion = innerClass;break;}}if (criterion == null) {throw new RuntimeException("Criterion not exist");}FullyQualifiedJavaType booleanPrimitive = FullyQualifiedJavaType.getBooleanPrimitiveInstance();Field pattern = new Field();pattern.setName("pattern");pattern.setVisibility(JavaVisibility.PRIVATE);pattern.setType(booleanPrimitive);criterion.addField(pattern);Method setPattern = new Method();setPattern.setVisibility(JavaVisibility.PUBLIC);setPattern.setName("setPattern");setPattern.addParameter(new Parameter(booleanPrimitive, "pattern"));setPattern.addBodyLine("this.pattern = pattern;");criterion.addMethod(setPattern);Method isPattern = new Method();isPattern.setVisibility(JavaVisibility.PUBLIC);isPattern.setReturnType(booleanPrimitive);isPattern.setName("isPattern");isPattern.addBodyLine("return pattern;");criterion.addMethod(isPattern);}public void addFindInSet(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {addFindInSetPattern(topLevelClass, introspectedTable, "findInSet", "find_in_set(" + valueName + ", " + columnName + ")");}public void addFindInSetPattern(TopLevelClass topLevelClass, IntrospectedTable introspectedTable, String opName, String pattern) {InnerClass criteria = null;// first, find the Criteria inner classfor (InnerClass innerClass : topLevelClass.getInnerClasses()) {if ("GeneratedCriteria".equals(innerClass.getType().getShortName())) { //$NON-NLS-1$criteria = innerClass;break;}}if (criteria == null) {throw new RuntimeException("GeneratedCriteria not exist");}for (IntrospectedColumn introspectedColumn : introspectedTable.getNonBLOBColumns()) {if (!introspectedColumn.isJdbcCharacterColumn()|| !introspectedColumn.isStringColumn()) {continue;}Method method = new Method();method.setVisibility(JavaVisibility.PUBLIC);method.addParameter(new Parameter(introspectedColumn.getFullyQualifiedJavaType(), "value")); //$NON-NLS-1$StringBuilder opNameBuilder = new StringBuilder(opName);opNameBuilder.setCharAt(0, Character.toUpperCase(opNameBuilder.charAt(0)));opName = opNameBuilder.toString();StringBuilder sb = new StringBuilder();sb.append(introspectedColumn.getJavaProperty());sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));sb.insert(0, "and"); //$NON-NLS-1$sb.append(opName);method.setName(sb.toString());method.setReturnType(FullyQualifiedJavaType.getCriteriaInstance());sb.setLength(0);sb.append("addCriterionPattern(\"").append(pattern.replaceAll(columnName, Ibatis2FormattingUtilities.getAliasedActualColumnName(introspectedColumn))).append("\", value, \"").append(introspectedColumn.getJavaProperty());sb.append("\");");method.addBodyLine(sb.toString());method.addBodyLine("return (Criteria) this;");criteria.addMethod(method);}}public void addPattern(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {addPatternMethod(topLevelClass, introspectedTable, "pattern");}public void addPatternMethod(TopLevelClass topLevelClass, IntrospectedTable introspectedTable, String opName){InnerClass criteria = null;// first, find the Criteria inner classfor (InnerClass innerClass : topLevelClass.getInnerClasses()) {if ("GeneratedCriteria".equals(innerClass.getType().getShortName())) { //$NON-NLS-1$criteria = innerClass;break;}}if (criteria == null) {throw new RuntimeException("GeneratedCriteria not exist");}for (IntrospectedColumn introspectedColumn : introspectedTable.getNonBLOBColumns()) {if (!introspectedColumn.isJdbcCharacterColumn()|| !introspectedColumn.isStringColumn()) {continue;}Method method = new Method();method.setVisibility(JavaVisibility.PUBLIC);method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "pattern"));method.addParameter(new Parameter(introspectedColumn.getFullyQualifiedJavaType(), "value"));StringBuilder opNameBuilder = new StringBuilder(opName);opNameBuilder.setCharAt(0, Character.toUpperCase(opNameBuilder.charAt(0)));opName = opNameBuilder.toString();StringBuilder sb = new StringBuilder();sb.append(introspectedColumn.getJavaProperty());sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));sb.insert(0, "and"); //$NON-NLS-1$sb.append(opName);method.setName(sb.toString());method.setReturnType(FullyQualifiedJavaType.getCriteriaInstance());sb.setLength(0);sb.append("addCriterionPattern(pattern.replaceAll(\"").append(columnName).append("\", \"").append(Ibatis2FormattingUtilities.getAliasedActualColumnName(introspectedColumn)).append("\")").append(", value, \"").append(introspectedColumn.getJavaProperty());sb.append("\");");method.addBodyLine(sb.toString());method.addBodyLine("return (Criteria) this;");criteria.addMethod(method);}}}
三、配置插件
<plugin type="com.mk.mybatisgenerator.plugins.MySQLMethodPlugin"/>