/*
原作者代码https://github.com/wucao/mybatis-generator-mysql-plugin
*/
package com.my.mbg;
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.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import java.util.List;
public class MySQLLimitPlugin extends PluginAdapter {
@Override
public boolean validate(List<String> list) {
return true;
}
/**
* 为每个Example类添加limit和offset属性已经set、get方法
*/
@Override
public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
PrimitiveTypeWrapper integerWrapper = FullyQualifiedJavaType.getIntInstance().getPrimitiveTypeWrapper();
Field limit = new Field();
limit.setName("limit");
limit.setVisibility(JavaVisibility.PRIVATE);
limit.setType(integerWrapper);
topLevelClass.addField(limit);
Method setLimit = new Method();
setLimit.setVisibility(JavaVisibility.PUBLIC);
setLimit.setName("setLimit");
setLimit.addParameter(new Parameter(integerWrapper, "limit"));
setLimit.addBodyLine("this.limit = limit;");
topLevelClass.addMethod(setLimit);
Method getLimit = new Method();
getLimit.setVisibility(JavaVisibility.PUBLIC);
getLimit.setReturnType(integerWrapper);
getLimit.setName("getLimit");
getLimit.addBodyLine("return limit;");
topLevelClass.addMethod(getLimit);
Field offset = new Field();
offset.setName("offset");
offset.setVisibility(JavaVisibility.PRIVATE);
offset.setType(integerWrapper);
topLevelClass.addField(offset);
Method setOffset = new Method();
setOffset.setVisibility(JavaVisibility.PUBLIC);
setOffset.setName("setOffset");
setOffset.addParameter(new Parameter(integerWrapper, "offset"));
setOffset.addBodyLine("this.offset = offset;");
topLevelClass.addMethod(setOffset);
Method getOffset = new Method();
getOffset.setVisibility(JavaVisibility.PUBLIC);
getOffset.setReturnType(integerWrapper);
getOffset.setName("getOffset");
getOffset.addBodyLine("return offset;");
topLevelClass.addMethod(getOffset);
return true;
}
/**
* 为Mapper.xml的selectByExample添加limit
*/
@Override
public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(XmlElement element,
IntrospectedTable introspectedTable) {
XmlElement ifLimitNotNullElement = new XmlElement("if");
ifLimitNotNullElement.addAttribute(new Attribute("test", "limit != null"));
XmlElement ifOffsetNotNullElement = new XmlElement("if");
ifOffsetNotNullElement.addAttribute(new Attribute("test", "offset != null"));
ifOffsetNotNullElement.addElement(new TextElement("limit ${offset}, ${limit}"));
ifLimitNotNullElement.addElement(ifOffsetNotNullElement);
XmlElement ifOffsetNullElement = new XmlElement("if");
ifOffsetNullElement.addAttribute(new Attribute("test", "offset == null"));
ifOffsetNullElement.addElement(new TextElement("limit ${limit}"));
ifLimitNotNullElement.addElement(ifOffsetNullElement);
element.addElement(ifLimitNotNullElement);
return true;
}
}
/*
新实现方式
*/
package com.my.mbg;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
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.javamapper.elements.AbstractJavaMapperMethodGenerator;
import org.mybatis.generator.codegen.mybatis3.xmlmapper.elements.AbstractXmlElementGenerator;
import org.mybatis.generator.internal.util.StringUtility;
import org.mybatis.generator.internal.util.messages.Messages;
import org.springframework.util.ReflectionUtils;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 另一种自己实现的Mybatis-Generator中可进行集成的分页插件代码
* 优点:参数易于理解
*
* 新增功能如下:
* 1.修改原先生成的*Example类名为*Template
* 2.修改dao *Mapper的方法中含有example的为template,参数也修改为template
* 3.修改xml *Mapper的sql中含有example的为template
* 4.dao *Mapper中加入注解,包引入
*/
public class MBGPlugin extends PluginAdapter {
/**
* 修改xml mapper、dao mapper中的example为另外自定义的命名
*/
private static final String QUERY_SUFFIX = "Template";
private static final String EXAMPLE_SUFFIX = "Example";
/**
* 修改Example类名为自定义的类名,源码拷贝
*/
private String searchString="Example$";
private String replaceString="Template";
private Pattern pattern;
@Override
public boolean validate(List<String> list) {
boolean valid = StringUtility.stringHasValue(this.searchString) && StringUtility.stringHasValue(this.replaceString);
if (valid) {
this.pattern = Pattern.compile(this.searchString);
} else {
if (!StringUtility.stringHasValue(this.searchString)) {
list.add(Messages.getString("ValidationError.18", "RenameExampleClassPlugin", "searchString"));
}
if (!StringUtility.stringHasValue(this.replaceString)) {
list.add(Messages.getString("ValidationError.18", "RenameExampleClassPlugin", "replaceString"));
}
}
return valid;
}
@Override
public void initialized(IntrospectedTable introspectedTable) {
String oldType = introspectedTable.getExampleType();
Matcher matcher = this.pattern.matcher(oldType);
oldType = matcher.replaceAll(this.replaceString);
introspectedTable.setExampleType(oldType);
}
/**
* 修改XML中的Example
*
* @param document
* @param introspectedTable
* @return
*/
@Override
public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
AbstractXmlElementGenerator generator = new AbstractXmlElementGenerator() {
@Override
public void addElements(XmlElement parentElement) {
java.lang.reflect.Field field = null;
try {
field = Attribute.class.getDeclaredField("value");
ReflectionUtils.makeAccessible(field);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
replaceExample(field, parentElement.getElements());
}
};
generator.setContext(context);
generator.setIntrospectedTable(introspectedTable);
generator.addElements(document.getRootElement());
return super.sqlMapDocumentGenerated(document, introspectedTable);
}
/**
* 递归修改XML中的Example
*
* @param field
* @param elements
*/
private void replaceExample(java.lang.reflect.Field field, List<Element> elements) {
if (CollectionUtils.isEmpty(elements)) {
return;
}
for (Element element : elements) {
if (!(element instanceof XmlElement)) {
continue;
}
XmlElement xmlElement = (XmlElement) element;
String name = xmlElement.getName();
switch (name) {
case "select":
case "update":
case "delete":
case "insert":
case "sql":
for (Attribute attribute : xmlElement.getAttributes()) {
String attributeName = attribute.getName();
String value = attribute.getValue();
if (!StringUtils.equals(attributeName, "id") || !StringUtils.contains(value, EXAMPLE_SUFFIX)) {
continue;
}
value = value.replace(EXAMPLE_SUFFIX, QUERY_SUFFIX);
ReflectionUtils.setField(field, attribute, value);
}
break;
case "foreach":
for (Attribute attribute : xmlElement.getAttributes()) {
String attributeName = attribute.getName();
String value = attribute.getValue();
if (!StringUtils.equals(attributeName, "collection") || !StringUtils.contains(value, EXAMPLE_SUFFIX.toLowerCase(Locale.ROOT))) {
continue;
}
value = value.replace(EXAMPLE_SUFFIX.toLowerCase(Locale.ROOT), QUERY_SUFFIX.toLowerCase(Locale.ROOT));
ReflectionUtils.setField(field, attribute, value);
}
break;
case "include":
for (Attribute attribute : xmlElement.getAttributes()) {
String attributeName = attribute.getName();
String value = attribute.getValue();
if (!StringUtils.equals(attributeName, "refid") || !StringUtils.contains(value, EXAMPLE_SUFFIX)) {
continue;
}
value = value.replace(EXAMPLE_SUFFIX, QUERY_SUFFIX);
ReflectionUtils.setField(field, attribute, value);
}
break;
default:
break;
}
List<Element> subElements = xmlElement.getElements();
this.replaceExample(field, subElements);
}
}
/**
* mapper层增加注解和包引入
* @param interfaze
* @param topLevelClass
* @param introspectedTable
* @return
*/
@Override
public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
if (introspectedTable.getTargetRuntime() == IntrospectedTable.TargetRuntime.MYBATIS3) {
interfaze.addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Mapper"));
interfaze.addAnnotation("@Mapper");
}
//仅修改dao mapper中的方法名
AbstractJavaMapperMethodGenerator generator = new AbstractJavaMapperMethodGenerator() {
@Override
public void addInterfaceElements(Interface interfaze) {
for (Method method : interfaze.getMethods()) {
String name = method.getName();
if (!StringUtils.contains(name, EXAMPLE_SUFFIX)) {
continue;
}
// 修改方法名称
method.setName(name.replace(EXAMPLE_SUFFIX, QUERY_SUFFIX));
List<Parameter> parameters = method.getParameters();
for (Parameter parameter : parameters) {
String parameterName = parameter.getName();
if (!StringUtils.contains(parameterName, EXAMPLE_SUFFIX.toLowerCase(Locale.ROOT))) {
continue;
}
// 修改变量名称
try {
java.lang.reflect.Field nameField = parameter.getClass().getDeclaredField("name");
ReflectionUtils.makeAccessible(nameField);
ReflectionUtils.setField(nameField, parameter, parameterName.replace(EXAMPLE_SUFFIX.toLowerCase(Locale.ROOT), QUERY_SUFFIX.toLowerCase(Locale.ROOT)));
} catch (Exception e) {
e.printStackTrace();
}
// 修改@Param注解value值
List<String> annotations = parameter.getAnnotations();
for (int i = 0; i < annotations.size(); i++) {
String annotation = annotations.get(i);
if (!StringUtils.contains(annotation, EXAMPLE_SUFFIX.toLowerCase(Locale.ROOT))) {
continue;
}
annotations.set(i, annotation.replace(EXAMPLE_SUFFIX.toLowerCase(Locale.ROOT), QUERY_SUFFIX.toLowerCase(Locale.ROOT)));
}
}
}
}
};
generator.setContext(context);
generator.setIntrospectedTable(introspectedTable);
generator.addInterfaceElements(interfaze);
return super.clientGenerated(interfaze, topLevelClass, introspectedTable);
}
/**
* 为每个Example类添加必要属性
*/
@Override
public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
PrimitiveTypeWrapper integerWrapper = FullyQualifiedJavaType.getIntInstance().getPrimitiveTypeWrapper();
Field limit = new Field();
limit.setName("currentPage");
limit.setVisibility(JavaVisibility.PRIVATE);
limit.setType(integerWrapper);
topLevelClass.addField(limit);
Field offset = new Field();
offset.setName("pageSize");
offset.setVisibility(JavaVisibility.PRIVATE);
offset.setType(integerWrapper);
topLevelClass.addField(offset);
Field pageCalc = new Field();
pageCalc.setName("pageCalc");
pageCalc.setVisibility(JavaVisibility.PRIVATE);
pageCalc.setType(integerWrapper);
topLevelClass.addField(pageCalc);
Method pageCalcConstructors = new Method();
pageCalcConstructors.setVisibility(JavaVisibility.PUBLIC);
pageCalcConstructors.setConstructor(true);
pageCalcConstructors.setName(topLevelClass.getType().getShortName());
pageCalcConstructors.addParameter(new Parameter(integerWrapper, "currentPage"));
pageCalcConstructors.addParameter(new Parameter(integerWrapper, "pageSize"));
pageCalcConstructors.addBodyLine("oredCriteria = new ArrayList<Criteria>();");
pageCalcConstructors.addBodyLine("this.pageSize = pageSize;");
pageCalcConstructors.addBodyLine("this.currentPage = currentPage;");
pageCalcConstructors.addBodyLine("this.pageCalc = (currentPage-1)*pageSize;");
topLevelClass.addMethod(pageCalcConstructors);
return true;
}
/**
* 为Mapper.xml的selectByExample添加分页逻辑
*/
@Override
public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(XmlElement element,
IntrospectedTable introspectedTable) {
XmlElement ifLimitNotNullElement = new XmlElement("if");
ifLimitNotNullElement.addAttribute(new Attribute("test", "currentPage != null"));
XmlElement ifOffsetNotNullElement = new XmlElement("if");
ifOffsetNotNullElement.addAttribute(new Attribute("test", "pageSize != null"));
ifOffsetNotNullElement.addElement(new TextElement("limit ${pageSize} offset ${pageCalc}"));
ifLimitNotNullElement.addElement(ifOffsetNotNullElement);
element.addElement(ifLimitNotNullElement);
return true;
}
}
generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<properties resource="generator.properties"/>
<context id="MySqlContext" targetRuntime="MyBatis3" defaultModelType="flat">
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<property name="javaFileEncoding" value="UTF-8"/>
<!-- 为模型生成序列化方法-->
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<!-- 为生成的Java模型创建一个toString方法 -->
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
<!--生成mapper.xml时覆盖原文件-->
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin" />
<plugin type="com.my.mbg.MBGPlugin"></plugin>
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true"/>
<property name="suppressDate" value="true"/>
<property name="addRemarkComments" value="false"/>
</commentGenerator>
<jdbcConnection driverClass="${jdbc.driverClass}"
connectionURL="${jdbc.connectionURL}"
userId="${jdbc.userId}"
password="${jdbc.password}">
<!--解决mysql驱动升级到8.0后不生成指定数据库代码的问题-->
<property name="nullCatalogMeansCurrent" value="true" />
</jdbcConnection>
<javaModelGenerator targetPackage="com.mbg.model" targetProject="src\main\java"/>
<sqlMapGenerator targetPackage="com.mbg.mapper" targetProject="src\main\resources"/>
<javaClientGenerator type="XMLMAPPER" targetPackage="com.mbg.mapper"
targetProject="src\main\java"/>
<!--生成全部表tableName设为%-->
<!--<table tableName="%">-->
<table tableName="ums_admin">
<generatedKey column="id" sqlStatement="MySql" identity="true"/>
</table>
</context>
</generatorConfiguration>
mybaties-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 引用db.properties配置文件 -->
<properties resource="generator.properties"/>
<!--
development : 开发模式
work : 工作模式
-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!-- 配置数据库连接信息 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClass}"/>
<property name="url" value="${jdbc.connectionURL}"/>
<property name="username" value="${jdbc.userId}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/mbg/mapper/UmsAdminMapper.xml"/>
</mappers>
</configuration>
generator.properties
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.connectionURL=jdbc:mysql://xx:3306/xx?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
jdbc.userId=root
jdbc.password=root