Mybatis-Generator扩展自定义的生成
发表于:2025-01-31 作者:千家信息网编辑
千家信息网最后更新 2025年01月31日,Mybatis-Generator 可自动生成Model、Dao、Mapper代码,但其自带生成的代码存在以下问题:生成的注释不是我们想要的,我们期望的是根据数据库表、字段生成不同的注释;分页代码生成
千家信息网最后更新 2025年01月31日Mybatis-Generator扩展自定义的生成
Mybatis-Generator 可自动生成Model、Dao、Mapper代码,但其自带生成的代码存在以下问题:
- 生成的注释不是我们想要的,我们期望的是根据数据库表、字段生成不同的注释;
- 分页代码生成缺失,每个公司的分页方式不同,尤其是老久项目或已发布API,不能随意变动,那么如何自适应分页代码生成;
- Mapper.xml没有group by相关代码生成;
- 重复生成代码时,Mapper.xml并不是覆盖原代码,而是对内容进行了追加;
- 序列化,
mybatis-generator
内置了SerializablePlugin
,但仅对Model,并没有对 Example序列化,在一些开发中是不够的; - 对Service Layer代码没有生成。
实际上,mybatis-generator
提供了PluginAdapter
供我们来继承,进行个性化的一些扩展(Plugin的相关内容是阅读本文的前置条件)如果不熟悉的同学,请自行补充,本文不对其进行相关介绍)。同时,本文不可能涵盖所有业务所需的扩展点,但是基本样板已有,可参考本文代码继续进行扩展。
一、注释的自定义生成
根据数据库表或字段的COMMENT
生成注释。@Date 生成的时间可根据需要自己定义格式。
package run.override;import java.util.Date;import java.util.Properties;import org.mybatis.generator.api.IntrospectedColumn;import org.mybatis.generator.api.IntrospectedTable;import org.mybatis.generator.api.dom.java.CompilationUnit;import org.mybatis.generator.api.dom.java.Field;import org.mybatis.generator.api.dom.java.InnerClass;import org.mybatis.generator.api.dom.java.InnerEnum;import org.mybatis.generator.api.dom.java.JavaElement;import org.mybatis.generator.api.dom.java.Method;import org.mybatis.generator.api.dom.java.Parameter;import org.mybatis.generator.api.dom.xml.XmlElement;import org.mybatis.generator.internal.DefaultCommentGenerator;import org.mybatis.generator.internal.util.StringUtility;/** * Comment Generator * @ClassName CommentGenerator * @Description * @author Marvis */public class CommentGenerator extends DefaultCommentGenerator { private Properties properties; private boolean suppressDate; private boolean suppressAllComments; public CommentGenerator() { this.properties = new Properties(); this.suppressDate = false; this.suppressAllComments = false; } public void addJavaFileComment(CompilationUnit compilationUnit) { compilationUnit.addFileCommentLine("/*** copyright (c) 2019 Marvis ***/"); } /** * XML file Comment */ public void addComment(XmlElement xmlElement) { if (this.suppressAllComments) { return; } } public void addRootComment(XmlElement rootElement) { } public void addConfigurationProperties(Properties properties) { this.properties.putAll(properties); this.suppressDate = StringUtility.isTrue(properties.getProperty("suppressDate")); this.suppressAllComments = StringUtility.isTrue(properties.getProperty("suppressAllComments")); } protected void addJavadocTag(JavaElement javaElement, boolean markAsDoNotDelete) { StringBuilder sb = new StringBuilder(); sb.append(" * "); sb.append("@date"); String s = getDateString(); if (s != null) { sb.append(' '); sb.append(s); } javaElement.addJavaDocLine(sb.toString()); } protected String getDateString() { if (this.suppressDate) { return null; } return new Date().toString(); } /** * Comment of Example inner class(GeneratedCriteria ,Criterion) */ public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) { if (this.suppressAllComments) { return; } innerClass.addJavaDocLine("/**"); innerClass.addJavaDocLine(" * " + introspectedTable.getFullyQualifiedTable().getDomainObjectName()+ ""); innerClass.addJavaDocLine(" * " + introspectedTable.getFullyQualifiedTable().toString()); addJavadocTag(innerClass, false); innerClass.addJavaDocLine(" */"); } public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) { if (this.suppressAllComments) { return; } StringBuilder sb = new StringBuilder(); innerEnum.addJavaDocLine("/**"); innerEnum.addJavaDocLine(" * " + introspectedTable.getFullyQualifiedTable().getAlias()+ ""); innerEnum.addJavaDocLine(" * " + introspectedTable.getFullyQualifiedTable()); innerEnum.addJavaDocLine(sb.toString()); addJavadocTag(innerEnum, false); innerEnum.addJavaDocLine(" */"); } /** * entity filed Comment */ public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { if (this.suppressAllComments) { return; }// if(introspectedColumn.getRemarks() != null && !introspectedColumn.getRemarks().trim().equals("")) field.addJavaDocLine("/**"); field.addJavaDocLine(" * " + introspectedColumn.getRemarks()); field.addJavaDocLine(" * @author " ); field.addJavaDocLine(" * @date " + getDateString() ); field.addJavaDocLine(" * @return"); field.addJavaDocLine(" */"); } /** * Comment of EXample filed */ public void addFieldComment(Field field, IntrospectedTable introspectedTable) { if (this.suppressAllComments) { return; } field.addJavaDocLine("/**"); addJavadocTag(field, false); field.addJavaDocLine(" */"); } /** * Comment of Example method */ public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) { if (this.suppressAllComments) { return; } } /** * * entity Getter Comment */ public void addGetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { if (this.suppressAllComments) { return; } method.addJavaDocLine("/**"); method.addJavaDocLine(" * @return " + introspectedTable.getFullyQualifiedTable().getAlias() + " : " + introspectedColumn.getRemarks()); method.addJavaDocLine(" */"); } public void addSetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { if (this.suppressAllComments) { return; } StringBuilder sb = new StringBuilder(); method.addJavaDocLine("/**"); Parameter parm = (Parameter) method.getParameters().get(0); sb.append(" * @param "); sb.append(parm.getName()); sb.append(" : "); sb.append(introspectedColumn.getRemarks()); method.addJavaDocLine(sb.toString()); method.addJavaDocLine(" */"); } /** * Comment of Example inner class(Criteria) */ public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) { if (this.suppressAllComments) { return; } innerClass.addJavaDocLine("/**"); innerClass.addJavaDocLine(" * " + introspectedTable.getFullyQualifiedTable().getAlias()+ ""); innerClass.addJavaDocLine(" * " + introspectedTable.getFullyQualifiedTable().toString()); addJavadocTag(innerClass, markAsDoNotDelete); innerClass.addJavaDocLine(" */"); }
Model 类注释(表的描述): MySQL。
1)EntityCommentPlugin
package run.override.model;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.Date;import java.util.List;import org.mybatis.generator.api.FullyQualifiedTable;import org.mybatis.generator.api.IntrospectedTable;import org.mybatis.generator.api.PluginAdapter;import org.mybatis.generator.api.dom.java.TopLevelClass;import org.mybatis.generator.internal.JDBCConnectionFactory;import org.mybatis.generator.internal.util.StringUtility;/** * Comment of Entity,only support MySQL * @ClassName CommentPlugin * @Description * @author Marvis */public class EntityCommentPlugin extends PluginAdapter { @Override public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { addModelClassComment(topLevelClass, introspectedTable); return super.modelBaseRecordClassGenerated(topLevelClass, introspectedTable); } @Override public boolean modelRecordWithBLOBsClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { addModelClassComment(topLevelClass, introspectedTable); return super.modelRecordWithBLOBsClassGenerated(topLevelClass, introspectedTable); } protected void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { FullyQualifiedTable table = introspectedTable.getFullyQualifiedTable(); String tableComment = getTableComment(table); topLevelClass.addJavaDocLine("/**"); if(StringUtility.stringHasValue(tableComment)) topLevelClass.addJavaDocLine(" * " + tableComment + ""); topLevelClass.addJavaDocLine(" * " + table.toString() + ""); topLevelClass.addJavaDocLine(" * @date " + new Date().toString()); topLevelClass.addJavaDocLine(" *"); topLevelClass.addJavaDocLine(" */"); } /** * @author Marvis * @date Jul 13, 2017 4:39:52 PM * @param table */ private String getTableComment(FullyQualifiedTable table) { String tableComment = ""; Connection connection = null; Statement statement = null; ResultSet rs = null; try { JDBCConnectionFactory jdbc = new JDBCConnectionFactory(context.getJdbcConnectionConfiguration()); connection = jdbc.getConnection(); statement = connection.createStatement(); rs = statement.executeQuery("SHOW CREATE TABLE " + table.getIntrospectedTableName()); if (rs != null && rs.next()) { String createDDL = rs.getString(2); int index = createDDL.indexOf("COMMENT='"); if (index < 0) { tableComment = ""; } else { tableComment = createDDL.substring(index + 9); tableComment = tableComment.substring(0, tableComment.length() - 1); } } } catch (SQLException e) { } finally { closeConnection(connection, statement, rs); } return tableComment; } /** * * @author Marvis * @date Jul 13, 2017 4:45:26 PM * @param connection * @param statement * @param rs */ private void closeConnection(Connection connection, Statement statement, ResultSet rs) { try { if (null != rs) rs.close(); } catch (SQLException e) { e.printStackTrace(); } finally { try { if (statement != null) statement.close(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (connection != null) connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } } /** * This plugin is always valid - no properties are required */ @Override public boolean validate(List warnings) { return true; }}
二、分页和分组代码生成
这里,我对Dao Model进行了通用方法的抽取,建立通用基类。同时,对其进行了一些扩展,增加分页和分组。
先对基类进行介绍。
1)BaseMapper
package cn.xxx.core.base.dao;import java.util.List;import org.apache.ibatis.annotations.Param;public interface BaseMapper { long countByExample(Example example); int deleteByExample(Example example); int deleteByPrimaryKey(ID id); int insert(T record); int insertSelective(T record); List selectByExample(Example example); T selectByPrimaryKey(ID id); int updateByExampleSelective(@Param("record") T record, @Param("example") Example example); int updateByExample(@Param("record") T record, @Param("example") Example example); int updateByPrimaryKeySelective(T record); int updateByPrimaryKey(T record);}
2)BaseExample
package cn.xxx.core.base.model;/** * BaseExample 基类 * @ClassName BaseExample * @Description 增加分页参数 * @author Marvis * @date Jul 31, 2017 11:26:53 AM */public abstract class BaseExample { protected PageInfo pageInfo; protected String groupByClause; public PageInfo getPageInfo() { return pageInfo; } public void setPageInfo(PageInfo pageInfo) { this.pageInfo = pageInfo; } public String getGroupByClause() { return groupByClause; } public void setGroupByClause(String groupByClause) { this.groupByClause = groupByClause; }}
3)PageInfo
package cn.xxx.core.base.model;import com.fasterxml.jackson.annotation.JsonIgnore;/** * 分页查询参数类 * * @author * */public class PageInfo { public static final int Default_PageSize = 20; // 当前页码 protected int currentPage = 1; // 总页数 protected int totalPage; // 总记录数 protected int totalCount; // 每页条数 protected int pageSize = Default_PageSize; // 开始 protected int pageBegin = 0; // 结束 protected int pageEnd = 20; /** * bean起始坐标(不包含) */ private Integer pageBeginId = null; public static final String PageQuery_classname = "pageInfo"; /** * 将分布参数传入处理,最终计算出当前页码PageQuery_currPage,开始坐标PageQuery_star, * 结束坐标PageQuery_end,总页数PageQuery_Psize * * 页数从1开始计数 * * @param totalCount * 记录总数 * @param pageSize * 每页显示个数 * @param currentPage * 当前页码 */ public void setPageParams(int totalCount, int pageSize, int currentPage) { this.totalPage = pageSize == 0 ? 1 : (int) Math.ceil((double) totalCount / (double) pageSize); this.totalCount = totalCount; this.pageSize = pageSize; this.currentPage = currentPage; float Psize_l = totalCount / (float) (this.pageSize); if (currentPage < 2) { currentPage = 1; pageBegin = 0; } else if (currentPage > Psize_l) { if (Psize_l == 0) { currentPage = 1; } else { currentPage = (int) Math.ceil(Psize_l); } pageBegin = (currentPage - 1) * this.pageSize; } else { pageBegin = (currentPage - 1) * this.pageSize; } pageSize = (int) Math.ceil(Psize_l); this.pageEnd = currentPage * this.pageSize; if (this.currentPage <= 0 || this.currentPage > this.totalPage) this.pageSize = 0; } /** * 将分布参数传入处理,最终计算出当前页码PageQuery_currPage,开始坐标PageQuery_star, * 结束坐标PageQuery_end,总页数PageQuery_Psize * * @param infoCount * 记录总数 */ public void setPageParams(int totalCount) { this.setPageParams(totalCount, this.pageSize, this.currentPage); } @Override public String toString() { return "PageInfo [currentPage=" + currentPage + ", totalPage=" + totalPage + ", totalCount=" + totalCount + ", pageSize=" + pageSize + ", pageBegin=" + pageBegin + ", pageEnd=" + pageEnd + ", pageBeginId=" + pageBeginId + "]"; } public int getCurrentPage() { return currentPage; } public int getTotalPage() { return totalPage; } public int getTotalCount() { return totalCount; } /** * 每页显示个数 */ public int getPageSize() { return pageSize; } @JsonIgnore public int getPageBegin() { return pageBegin; } @JsonIgnore public int getPageEnd() { return pageEnd; } /** * bean起始id(不包含) */ @JsonIgnore public Integer getPageBeginId() { return pageBeginId; } /** * 请求页 */ public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } /** * 每页显示个数 */ public void setPageSize(int pageSize) { this.pageSize = pageSize; }}
4)PaginationPlugin
分页扩展。并且Example
继承BaseExample
。
package run.override.pagination;import org.mybatis.generator.api.IntrospectedTable;import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;import org.mybatis.generator.api.dom.java.TopLevelClass;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 run.override.mapper.SqlMapIsMergeablePlugin;import run.override.proxyFactory.FullyQualifiedJavaTypeProxyFactory;public class PaginationPlugin extends SqlMapIsMergeablePlugin { @Override public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { FullyQualifiedJavaType baseExampleType = FullyQualifiedJavaTypeProxyFactory.getBaseExampleInstance(); topLevelClass.setSuperClass(baseExampleType); topLevelClass.addImportedType(baseExampleType); return super.modelExampleClassGenerated(topLevelClass, introspectedTable); } @Override public boolean sqlMapSelectByExampleWithBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { XmlElement isNotNullElement1 = new XmlElement("if"); isNotNullElement1.addAttribute(new Attribute("test", "groupByClause != null")); isNotNullElement1.addElement(new TextElement("group by ${groupByClause}")); element.addElement(5, isNotNullElement1); XmlElement isNotNullElement = new XmlElement("if"); isNotNullElement.addAttribute(new Attribute("test", "pageInfo != null")); isNotNullElement.addElement(new TextElement("limit #{pageInfo.pageBegin} , #{pageInfo.pageSize}")); element.addElement(isNotNullElement); return super.sqlMapUpdateByExampleWithBLOBsElementGenerated(element, introspectedTable); } @Override public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { XmlElement isNotNullElement1 = new XmlElement("if"); isNotNullElement1.addAttribute(new Attribute("test", "groupByClause != null")); isNotNullElement1.addElement(new TextElement("group by ${groupByClause}")); element.addElement(5, isNotNullElement1); XmlElement isNotNullElement = new XmlElement("if"); isNotNullElement.addAttribute(new Attribute("test", "pageInfo != null")); isNotNullElement.addElement(new TextElement("limit #{pageInfo.pageBegin} , #{pageInfo.pageSize}")); element.addElement(isNotNullElement); return super.sqlMapUpdateByExampleWithoutBLOBsElementGenerated(element, introspectedTable); } @Override public boolean sqlMapCountByExampleElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { XmlElement answer = new XmlElement("select"); String fqjt = introspectedTable.getExampleType(); answer.addAttribute(new Attribute("id", introspectedTable.getCountByExampleStatementId())); answer.addAttribute(new Attribute("parameterType", fqjt)); answer.addAttribute(new Attribute("resultType", "java.lang.Integer")); this.context.getCommentGenerator().addComment(answer); StringBuilder sb = new StringBuilder(); sb.append("select count(1) from "); sb.append(introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime()); XmlElement ifElement = new XmlElement("if"); ifElement.addAttribute(new Attribute("test", "_parameter != null")); XmlElement includeElement = new XmlElement("include"); includeElement.addAttribute(new Attribute("refid", introspectedTable.getExampleWhereClauseId())); ifElement.addElement(includeElement); element.getElements().clear(); element.getElements().add(new TextElement(sb.toString())); element.getElements().add(ifElement); return super.sqlMapUpdateByExampleWithoutBLOBsElementGenerated(element, introspectedTable); }}
5)FullyQualifiedJavaTypeProxyFactory
package run.override.proxyFactory;import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;public class FullyQualifiedJavaTypeProxyFactory extends FullyQualifiedJavaType{ private static FullyQualifiedJavaType pageInfoInstance = new FullyQualifiedJavaType("cn.xxx.core.base.model.PageInfo"); private static FullyQualifiedJavaType baseExampleInstance = new FullyQualifiedJavaType("cn.xxx.core.base.model.BaseExample"); private static FullyQualifiedJavaType baseMapperInstance = new FullyQualifiedJavaType("cn.xxx.core.base.dao.BaseMapper"); private static FullyQualifiedJavaType baseServiceInstance = new FullyQualifiedJavaType("cn.xxx.core.base.service.BaseService"); private static FullyQualifiedJavaType baseServiceImplInstance = new FullyQualifiedJavaType("cn.xxx.core.base.service.impl.BaseServiceImpl"); public FullyQualifiedJavaTypeProxyFactory(String fullTypeSpecification) { super(fullTypeSpecification); } public static final FullyQualifiedJavaType getPageInfoInstanceInstance() { return pageInfoInstance; } public static final FullyQualifiedJavaType getBaseExampleInstance() { return baseExampleInstance; } public static final FullyQualifiedJavaType getBaseMapperInstance() { return baseMapperInstance; } public static final FullyQualifiedJavaType getBaseServiceInstance() { return baseServiceInstance; } public static final FullyQualifiedJavaType getBaseServiceImplInstance() { return baseServiceImplInstance; }}
三、Dao 生成代码简化
1)ClientDaoPlugin
package run.override.dao;import java.util.Arrays;import java.util.List;import java.util.stream.Collectors;import org.mybatis.generator.api.IntrospectedTable;import org.mybatis.generator.api.JavaTypeResolver;import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;import org.mybatis.generator.api.dom.java.Interface;import org.mybatis.generator.api.dom.java.Method;import org.mybatis.generator.api.dom.java.TopLevelClass;import org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl;import run.override.model.EntityCommentPlugin;import run.override.proxyFactory.FullyQualifiedJavaTypeProxyFactory;/** * javaClient("XMLMAPPER") extended * * @ClassName ClientDaoPlugin * @Description Mapper.java * @author Marvis */public class ClientDaoPlugin extends EntityCommentPlugin { @Override public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { JavaTypeResolver javaTypeResolver = new JavaTypeResolverDefaultImpl(); FullyQualifiedJavaType calculateJavaType = javaTypeResolver .calculateJavaType(introspectedTable.getPrimaryKeyColumns().get(0)); FullyQualifiedJavaType superInterfaceType = new FullyQualifiedJavaType( new StringBuilder("BaseMapper<") .append(introspectedTable.getBaseRecordType()) .append(",") .append(introspectedTable.getExampleType()) .append(",") .append(calculateJavaType.getShortName()) .append(">") .toString() ); FullyQualifiedJavaType baseMapperInstance = FullyQualifiedJavaTypeProxyFactory.getBaseMapperInstance(); interfaze.addSuperInterface(superInterfaceType); interfaze.addImportedType(baseMapperInstance); List changeMethods = interfaze.getMethods().stream() .filter(method -> method.getName().endsWith("WithBLOBs") || method.getReturnType().toString().endsWith("WithBLOBs") || Arrays.toString(method.getParameters().toArray()).contains("WithBLOBs")) .collect(Collectors.toList()); interfaze.getMethods().retainAll(changeMethods); if (changeMethods.isEmpty()) interfaze.getImportedTypes().removeIf(javaType -> javaType.getFullyQualifiedName().equals("java.util.List") || javaType.getFullyQualifiedName().equals("org.apache.ibatis.annotations.Param")); return super.clientGenerated(interfaze, topLevelClass, introspectedTable); }}
四、修正
重复生成时Mapper.xml不是覆盖原代码,而是对内容进行了追加。
1)SqlMapIsMergeablePlugin
package run.override.mapper;import org.mybatis.generator.api.GeneratedXmlFile;import org.mybatis.generator.api.IntrospectedTable;import run.override.dao.ClientDaoPlugin;public class SqlMapIsMergeablePlugin extends ClientDaoPlugin { @Override public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) { //重新生成代码,xml内容覆盖 sqlMap.setMergeable(false); return super.sqlMapGenerated(sqlMap, introspectedTable); }}
五、序列化自定义扩展
增加Example
的序列化,并增加@SuppressWarnings("serial")
注解。
1)SerializablePlugin
package run.override;import java.util.List;import java.util.Properties;import org.mybatis.generator.api.IntrospectedTable;import org.mybatis.generator.api.PluginAdapter;import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;import org.mybatis.generator.api.dom.java.TopLevelClass;public class SerializablePlugin extends PluginAdapter { private FullyQualifiedJavaType serializable; private FullyQualifiedJavaType gwtSerializable; private boolean addGWTInterface; private boolean suppressJavaInterface; public SerializablePlugin() { this.serializable = new FullyQualifiedJavaType("java.io.Serializable"); this.gwtSerializable = new FullyQualifiedJavaType("com.google.gwt.user.client.rpc.IsSerializable"); } @Override public void setProperties(Properties properties) { super.setProperties(properties); this.addGWTInterface = Boolean.valueOf(properties.getProperty("addGWTInterface")).booleanValue(); this.suppressJavaInterface = Boolean.valueOf(properties.getProperty("suppressJavaInterface")).booleanValue(); } @Override public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { makeSerializable(topLevelClass, introspectedTable); return true; } @Override public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { makeSerializable(topLevelClass, introspectedTable); return true; } @Override public boolean modelRecordWithBLOBsClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { makeSerializable(topLevelClass, introspectedTable); return true; } @Override public boolean modelExampleClassGenerated(TopLevelClass topLevelClass,IntrospectedTable introspectedTable){ makeSerializable(topLevelClass, introspectedTable); return true; } protected void makeSerializable(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { if (this.addGWTInterface) { topLevelClass.addImportedType(this.gwtSerializable); topLevelClass.addSuperInterface(this.gwtSerializable); } if (!(this.suppressJavaInterface)) { topLevelClass.addImportedType(this.serializable); topLevelClass.addSuperInterface(this.serializable); topLevelClass.addAnnotation("@SuppressWarnings(\"serial\")"); } } /** * This plugin is always valid - no properties are required */ @Override public boolean validate(List warnings) { return true; }}
六、服务层代码自定义生成
重写Context
,ConfigurationParser
,MyBatisGeneratorConfigurationParser
,增加服务层生成逻辑。
先对Service基类进行介绍。
1)BaseService
package cn.xxx.core.base.service;import java.util.List;import org.apache.ibatis.annotations.Param;import cn.xxx.core.base.model.BaseExample;import cn.xxx.core.base.model.PageInfo;public interface BaseService { long countByExample(Example example); int deleteByExample(Example example); int deleteByPrimaryKey(ID id); int insert(T record); int insertSelective(T record); List selectByExample(Example example); /** * return T object * @author Marvis * @date May 23, 2018 11:37:11 AM * @param example * @return */ T selectByCondition(Example example); /** * if pageInfo == null * then return result of selectByExample(example) * @author Marvis * @date Jul 13, 2017 5:24:35 PM * @param example * @param pageInfo * @return */ List selectByPageExmple(Example example, PageInfo pageInfo); T selectByPrimaryKey(ID id); int updateByExampleSelective(@Param("record") T record, @Param("example") Example example); int updateByExample(@Param("record") T record, @Param("example") Example example); int updateByPrimaryKeySelective(T record); int updateByPrimaryKey(T record);}
2)BaseServiceImpl
package cn.xxx.core.base.service.impl;import java.util.List;import cn.xxx.core.base.dao.BaseMapper;import cn.xxx.core.base.model.BaseExample;import cn.xxx.core.base.model.PageInfo;import cn.xxx.core.base.service.BaseService;public abstract class BaseServiceImpl implements BaseService { private BaseMapper mapper; public void setMapper(BaseMapper mapper) { this.mapper = mapper; } public long countByExample(Example example) { return mapper.countByExample(example); } @Override public int deleteByExample(Example example) { return mapper.deleteByExample(example); } @Override public int deleteByPrimaryKey(ID id) { return mapper.deleteByPrimaryKey(id); } @Override public int insert(T record) { return mapper.insert(record); } @Override public int insertSelective(T record) { return mapper.insertSelective(record); } @Override public List selectByExample(Example example) { return mapper.selectByExample(example); } @Override public T selectByCondition(Example example) { List datas = selectByExample(example); return datas != null && datas.size() == 0 ? null : datas.get(0); } @Override public List selectByPageExmple(Example example, PageInfo pageInfo) { if(pageInfo != null){ example.setPageInfo(pageInfo); pageInfo.setPageParams(Long.valueOf(this.countByExample(example)).intValue()); } return this.selectByExample(example); } @Override public T selectByPrimaryKey(ID id) { return mapper.selectByPrimaryKey(id); } @Override public int updateByExampleSelective(T record, Example example) { return mapper.updateByExampleSelective(record, example); } @Override public int updateByExample(T record, Example example) { return mapper.updateByExample(record, example); } @Override public int updateByPrimaryKeySelective(T record) { return mapper.updateByPrimaryKeySelective(record); } @Override public int updateByPrimaryKey(T record) { return mapper.updateByPrimaryKey(record); }}
3)ServiceLayerPlugin
package run.override.service;import org.mybatis.generator.api.GeneratedJavaFile;import org.mybatis.generator.api.IntrospectedTable;import org.mybatis.generator.api.JavaTypeResolver;import org.mybatis.generator.api.dom.java.CompilationUnit;import org.mybatis.generator.api.dom.java.Field;import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;import org.mybatis.generator.api.dom.java.Interface;import org.mybatis.generator.api.dom.java.JavaVisibility;import org.mybatis.generator.api.dom.java.Method;import org.mybatis.generator.api.dom.java.Parameter;import org.mybatis.generator.api.dom.java.TopLevelClass;import org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl;import run.override.pagination.PaginationPlugin;import run.override.proxyFactory.FullyQualifiedJavaTypeProxyFactory;import java.util.ArrayList;import java.util.List;import java.util.stream.Collectors;public class ServiceLayerPlugin extends PaginationPlugin { /** * 生成额外java文件 */ @Override public List contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) { ContextOverride context = (ContextOverride) introspectedTable.getContext(); ServiceGeneratorConfiguration serviceGeneratorConfiguration; if ((serviceGeneratorConfiguration = context.getServiceGeneratorConfiguration()) == null) return null; String targetPackage = serviceGeneratorConfiguration.getTargetPackage(); String targetProject = serviceGeneratorConfiguration.getTargetProject(); String implementationPackage = serviceGeneratorConfiguration.getImplementationPackage(); CompilationUnit addServiceInterface = addServiceInterface(introspectedTable, targetPackage); CompilationUnit addServiceImplClazz = addServiceImplClazz(introspectedTable, targetPackage, implementationPackage); GeneratedJavaFile gjfServiceInterface = new GeneratedJavaFile(addServiceInterface, targetProject, this.context.getProperty("javaFileEncoding"), this.context.getJavaFormatter()); GeneratedJavaFile gjfServiceImplClazz = new GeneratedJavaFile(addServiceImplClazz, targetProject, this.context.getProperty("javaFileEncoding"), this.context.getJavaFormatter()); List list = new ArrayList<>(); list.add(gjfServiceInterface); list.add(gjfServiceImplClazz); return list; } protected CompilationUnit addServiceInterface(IntrospectedTable introspectedTable, String targetPackage) { String entityClazzType = introspectedTable.getBaseRecordType(); String serviceSuperPackage = targetPackage; String entityExampleClazzType = introspectedTable.getExampleType(); String domainObjectName = introspectedTable.getFullyQualifiedTable().getDomainObjectName(); JavaTypeResolver javaTypeResolver = new JavaTypeResolverDefaultImpl(); FullyQualifiedJavaType calculateJavaType = javaTypeResolver .calculateJavaType(introspectedTable.getPrimaryKeyColumns().get(0)); StringBuilder builder = new StringBuilder(); FullyQualifiedJavaType superInterfaceType = new FullyQualifiedJavaType( builder.append("BaseService<") .append(entityClazzType) .append(",") .append(entityExampleClazzType) .append(",") .append(calculateJavaType.getShortName()).append(">").toString()); Interface serviceInterface = new Interface( builder.delete(0, builder.length()) .append(serviceSuperPackage) .append(".") .append(domainObjectName) .append("Service") .toString() ); serviceInterface.addSuperInterface(superInterfaceType); serviceInterface.setVisibility(JavaVisibility.PUBLIC); FullyQualifiedJavaType baseServiceInstance = FullyQualifiedJavaTypeProxyFactory.getBaseServiceInstance(); FullyQualifiedJavaType modelJavaType = new FullyQualifiedJavaType(entityClazzType); FullyQualifiedJavaType exampleJavaType = new FullyQualifiedJavaType(entityExampleClazzType); serviceInterface.addImportedType(baseServiceInstance); serviceInterface.addImportedType(modelJavaType); serviceInterface.addImportedType(exampleJavaType); serviceInterface.addFileCommentLine("/*** copyright (c) 2019 Marvis ***/"); this.additionalServiceMethods(introspectedTable, serviceInterface); return serviceInterface; } protected CompilationUnit addServiceImplClazz(IntrospectedTable introspectedTable, String targetPackage, String implementationPackage) { String entityClazzType = introspectedTable.getBaseRecordType(); String serviceSuperPackage = targetPackage; String serviceImplSuperPackage = implementationPackage; String entityExampleClazzType = introspectedTable.getExampleType(); String javaMapperType = introspectedTable.getMyBatis3JavaMapperType(); String domainObjectName = introspectedTable.getFullyQualifiedTable().getDomainObjectName(); JavaTypeResolver javaTypeResolver = new JavaTypeResolverDefaultImpl(); FullyQualifiedJavaType calculateJavaType = javaTypeResolver .calculateJavaType(introspectedTable.getPrimaryKeyColumns().get(0)); StringBuilder builder = new StringBuilder(); FullyQualifiedJavaType superClazzType = new FullyQualifiedJavaType( builder.append("BaseServiceImpl<") .append(entityClazzType) .append(",") .append(entityExampleClazzType) .append(",") .append(calculateJavaType.getShortName()).append(">") .toString() ); FullyQualifiedJavaType implInterfaceType = new FullyQualifiedJavaType( builder.delete(0, builder.length()) .append(serviceSuperPackage) .append(".") .append(domainObjectName) .append("Service") .toString() ); TopLevelClass serviceImplClazz = new TopLevelClass( builder.delete(0, builder.length()) .append(serviceImplSuperPackage) .append(".") .append(domainObjectName) .append("ServiceImpl") .toString() ); serviceImplClazz.addSuperInterface(implInterfaceType); serviceImplClazz.setSuperClass(superClazzType); serviceImplClazz.setVisibility(JavaVisibility.PUBLIC); serviceImplClazz.addAnnotation("@Service"); FullyQualifiedJavaType baseServiceInstance = FullyQualifiedJavaTypeProxyFactory.getBaseServiceImplInstance(); FullyQualifiedJavaType modelJavaType = new FullyQualifiedJavaType(entityClazzType); FullyQualifiedJavaType exampleJavaType = new FullyQualifiedJavaType(entityExampleClazzType); serviceImplClazz .addImportedType(new FullyQualifiedJavaType("org.springframework.beans.factory.annotation.Autowired")); serviceImplClazz.addImportedType(new FullyQualifiedJavaType("org.springframework.stereotype.Service")); serviceImplClazz.addImportedType(baseServiceInstance); serviceImplClazz.addImportedType(modelJavaType); serviceImplClazz.addImportedType(exampleJavaType); serviceImplClazz.addImportedType(implInterfaceType); FullyQualifiedJavaType logType = new FullyQualifiedJavaType("org.slf4j.Logger"); FullyQualifiedJavaType logFactoryType = new FullyQualifiedJavaType("org.slf4j.LoggerFactory"); Field logField = new Field(); logField.setVisibility(JavaVisibility.PRIVATE); logField.setStatic(true); logField.setFinal(true); logField.setType(logType); logField.setName("logger"); logField.setInitializationString( builder.delete(0, builder.length()) .append("LoggerFactory.getLogger(") .append(domainObjectName) .append("ServiceImpl.class)") .toString() ); logField.addAnnotation(""); logField.addAnnotation("@SuppressWarnings(\"unused\")"); serviceImplClazz.addField(logField); serviceImplClazz.addImportedType(logType); serviceImplClazz.addImportedType(logFactoryType); String mapperName = builder.delete(0, builder.length()) .append(Character.toLowerCase(domainObjectName.charAt(0))) .append(domainObjectName.substring(1)) .append("Mapper") .toString(); FullyQualifiedJavaType JavaMapperType = new FullyQualifiedJavaType(javaMapperType); Field mapperField = new Field(); mapperField.setVisibility(JavaVisibility.PUBLIC); mapperField.setType(JavaMapperType);// Mapper.java mapperField.setName(mapperName); mapperField.addAnnotation("@Autowired"); serviceImplClazz.addField(mapperField); serviceImplClazz.addImportedType(JavaMapperType); Method mapperMethod = new Method(); mapperMethod.setVisibility(JavaVisibility.PUBLIC); mapperMethod.setName("setMapper"); mapperMethod.addBodyLine("super.setMapper(" + mapperName + ");"); mapperMethod.addAnnotation("@Autowired"); serviceImplClazz.addMethod(mapperMethod); serviceImplClazz.addFileCommentLine("/*** copyright (c) 2019 Marvis ***/"); serviceImplClazz .addImportedType(new FullyQualifiedJavaType("org.springframework.beans.factory.annotation.Autowired")); this.additionalServiceImplMethods(introspectedTable, serviceImplClazz, mapperName); return serviceImplClazz; } protected void additionalServiceMethods(IntrospectedTable introspectedTable, Interface serviceInterface) { if (this.notHasBLOBColumns(introspectedTable)) return; introspectedTable.getGeneratedJavaFiles().stream().filter(file -> file.getCompilationUnit().isJavaInterface() && file.getCompilationUnit().getType().getShortName().endsWith("Mapper")).map(GeneratedJavaFile::getCompilationUnit).forEach( compilationUnit -> ((Interface) compilationUnit).getMethods().forEach( m -> serviceInterface.addMethod(this.additionalServiceLayerMethod(serviceInterface, m)))); } protected void additionalServiceImplMethods(IntrospectedTable introspectedTable, TopLevelClass clazz, String mapperName) { if (this.notHasBLOBColumns(introspectedTable)) return; introspectedTable.getGeneratedJavaFiles().stream().filter(file -> file.getCompilationUnit().isJavaInterface() && file.getCompilationUnit().getType().getShortName().endsWith("Mapper")).map(GeneratedJavaFile::getCompilationUnit).forEach( compilationUnit -> ((Interface) compilationUnit).getMethods().forEach(m -> { Method serviceImplMethod = this.additionalServiceLayerMethod(clazz, m); serviceImplMethod.addAnnotation("@Override"); serviceImplMethod.addBodyLine(this.generateBodyForServiceImplMethod(mapperName, m)); clazz.addMethod(serviceImplMethod); })); } private boolean notHasBLOBColumns(IntrospectedTable introspectedTable) { return !introspectedTable.hasBLOBColumns(); } private Method additionalServiceLayerMethod(CompilationUnit compilation, Method m) { Method method = new Method(); method.setVisibility(JavaVisibility.PUBLIC); method.setName(m.getName()); List parameters = m.getParameters(); method.getParameters().addAll(parameters.stream().peek(param -> param.getAnnotations().clear()).collect(Collectors.toList())); method.setReturnType(m.getReturnType()); compilation.addImportedType( new FullyQualifiedJavaType(m.getReturnType().getFullyQualifiedNameWithoutTypeParameters())); return method; } private String generateBodyForServiceImplMethod(String mapperName, Method m) { StringBuilder sbf = new StringBuilder("return "); sbf.append(mapperName).append(".").append(m.getName()).append("("); boolean singleParam = true; for (Parameter parameter : m.getParameters()) { if (singleParam) singleParam = !singleParam; else sbf.append(", "); sbf.append(parameter.getName()); } sbf.append(");"); return sbf.toString(); }}
4)ContextOverride
package run.override.service;import java.util.List;import org.mybatis.generator.api.dom.xml.XmlElement;import org.mybatis.generator.config.Context;import org.mybatis.generator.config.ModelType;public class ContextOverride extends Context{ //添加ServiceGeneratorConfiguration private ServiceGeneratorConfiguration serviceGeneratorConfiguration; public ContextOverride(ModelType defaultModelType) { super(defaultModelType); } public ServiceGeneratorConfiguration getServiceGeneratorConfiguration() { return serviceGeneratorConfiguration; } public void setServiceGeneratorConfiguration(ServiceGeneratorConfiguration serviceGeneratorConfiguration) { this.serviceGeneratorConfiguration = serviceGeneratorConfiguration; } @Override public void validate(List errors) { if(serviceGeneratorConfiguration != null) serviceGeneratorConfiguration.validate(errors, this.getId()); super.validate(errors); } public XmlElement toXmlElement() { XmlElement xmlElement = super.toXmlElement(); if (serviceGeneratorConfiguration != null) xmlElement.addElement(serviceGeneratorConfiguration.toXmlElement()); return xmlElement; }}
5)MyBatisGeneratorConfigurationParserOverride
package run.override.service;import java.util.Properties;import org.mybatis.generator.config.Configuration;import org.mybatis.generator.config.Context;import org.mybatis.generator.config.JavaClientGeneratorConfiguration;import org.mybatis.generator.config.ModelType;import org.mybatis.generator.config.PluginConfiguration;import org.mybatis.generator.config.xml.MyBatisGeneratorConfigurationParser;import org.mybatis.generator.exception.XMLParserException;import org.mybatis.generator.internal.util.StringUtility;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.w3c.dom.NodeList;public class MyBatisGeneratorConfigurationParserOverride extends MyBatisGeneratorConfigurationParser { public MyBatisGeneratorConfigurationParserOverride(Properties extraProperties) { super(extraProperties); } private void parseJavaServiceGenerator(Context context, Node node) { ContextOverride contextOverride = ContextOverride.class.cast(context); ////替换Context ServiceGeneratorConfiguration serviceGeneratorConfiguration = new ServiceGeneratorConfiguration(); contextOverride.setServiceGeneratorConfiguration(serviceGeneratorConfiguration); Properties attributes = parseAttributes(node); String targetPackage = attributes.getProperty("targetPackage"); String targetProject = attributes.getProperty("targetProject"); String implementationPackage = attributes.getProperty("implementationPackage"); serviceGeneratorConfiguration.setTargetPackage(targetPackage); serviceGeneratorConfiguration.setTargetProject(targetProject); serviceGeneratorConfiguration.setImplementationPackage(implementationPackage); NodeList nodeList = node.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { Node childNode = nodeList.item(i); if (childNode.getNodeType() == Node.ELEMENT_NODE && "property".equals(childNode.getNodeName())) parseProperty(serviceGeneratorConfiguration, childNode); } } @Override public Configuration parseConfiguration(Element rootNode) throws XMLParserException { Configuration configuration = new Configuration(); NodeList nodeList = rootNode.getChildNodes(); for (int i = 0; i < nodeList.getLength(); ++i) { Node childNode = nodeList.item(i); if (childNode.getNodeType() != 1) { continue; } if ("properties".equals(childNode.getNodeName())) parseProperties(configuration, childNode); else if ("classPathEntry".equals(childNode.getNodeName())) parseClassPathEntry(configuration, childNode); else if ("context".equals(childNode.getNodeName())) { parseContext(configuration, childNode); } } return configuration; } private void parseContext(Configuration configuration, Node node) { Properties attributes = parseAttributes(node); String defaultModelType = attributes.getProperty("defaultModelType"); String targetRuntime = attributes.getProperty("targetRuntime"); String introspectedColumnImpl = attributes.getProperty("introspectedColumnImpl"); String id = attributes.getProperty("id"); ModelType mt = defaultModelType != null ? ModelType.getModelType(defaultModelType) : null; Context context = new ContextOverride(mt); context.setId(id); if (StringUtility.stringHasValue(introspectedColumnImpl)) context.setIntrospectedColumnImpl(introspectedColumnImpl); if (StringUtility.stringHasValue(targetRuntime)) context.setTargetRuntime(targetRuntime); configuration.addContext(context); NodeList nodeList = node.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { Node childNode = nodeList.item(i); if (childNode.getNodeType() != 1) continue; if ("property".equals(childNode.getNodeName())) { parseProperty(context, childNode); continue; } if ("plugin".equals(childNode.getNodeName())) { parsePlugin(context, childNode); continue; } if ("commentGenerator".equals(childNode.getNodeName())) { parseCommentGenerator(context, childNode); continue; } if ("jdbcConnection".equals(childNode.getNodeName())) { parseJdbcConnection(context, childNode); continue; } if ("connectionFactory".equals(childNode.getNodeName())) { parseConnectionFactory(context, childNode); continue; } if ("javaModelGenerator".equals(childNode.getNodeName())) { parseJavaModelGenerator(context, childNode); continue; } if ("javaTypeResolver".equals(childNode.getNodeName())) { parseJavaTypeResolver(context, childNode); continue; } if ("sqlMapGenerator".equals(childNode.getNodeName())) { parseSqlMapGenerator(context, childNode); continue; } if ("javaClientGenerator".equals(childNode.getNodeName())) { parseJavaClientGenerator(context, childNode); continue; } if ("javaServiceGenerator".equals(childNode.getNodeName())) { parseJavaServiceGenerator(context, childNode); continue; } if ("table".equals(childNode.getNodeName())) parseTable(context, childNode); } } private void parsePlugin(Context context, Node node) { PluginConfiguration pluginConfiguration = new PluginConfiguration(); context.addPluginConfiguration(pluginConfiguration); Properties attributes = parseAttributes(node); String type = attributes.getProperty("type"); pluginConfiguration.setConfigurationType(type); NodeList nodeList = node.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { Node childNode = nodeList.item(i); if (childNode.getNodeType() == 1 && "property".equals(childNode.getNodeName())) parseProperty(pluginConfiguration, childNode); } } private void parseJavaClientGenerator(Context context, Node node) { JavaClientGeneratorConfiguration javaClientGeneratorConfiguration = new JavaClientGeneratorConfiguration(); context.setJavaClientGeneratorConfiguration(javaClientGeneratorConfiguration); Properties attributes = parseAttributes(node); String type = attributes.getProperty("type"); String targetPackage = attributes.getProperty("targetPackage"); String targetProject = attributes.getProperty("targetProject"); String implementationPackage = attributes.getProperty("implementationPackage"); javaClientGeneratorConfiguration.setConfigurationType(type); javaClientGeneratorConfiguration.setTargetPackage(targetPackage); javaClientGeneratorConfiguration.setTargetProject(targetProject); javaClientGeneratorConfiguration.setImplementationPackage(implementationPackage); NodeList nodeList = node.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { Node childNode = nodeList.item(i); if (childNode.getNodeType() == 1 && "property".equals(childNode.getNodeName())) parseProperty(javaClientGeneratorConfiguration, childNode); } }}
6)ServiceGeneratorConfiguration
package run.override.service;import java.util.List;import org.mybatis.generator.api.dom.xml.Attribute;import org.mybatis.generator.api.dom.xml.XmlElement;import org.mybatis.generator.config.PropertyHolder;import org.mybatis.generator.internal.util.StringUtility;import org.mybatis.generator.internal.util.messages.Messages;public class ServiceGeneratorConfiguration extends PropertyHolder { private String targetPackage; private String implementationPackage; private String targetProject; /** * */ public ServiceGeneratorConfiguration() { super(); } public String getTargetPackage() { return targetPackage; } public void setTargetPackage(String targetPackage) { this.targetPackage = targetPackage; } public String getImplementationPackage() { return implementationPackage; } public void setImplementationPackage(String implementationPackage) { this.implementationPackage = implementationPackage; } public String getTargetProject() { return targetProject; } public void setTargetProject(String targetProject) { this.targetProject = targetProject; } public XmlElement toXmlElement() { XmlElement answer = new XmlElement("javaServiceGenerator"); if (targetPackage != null) { answer.addAttribute(new Attribute("targetPackage", targetPackage)); } if (implementationPackage != null) { answer.addAttribute(new Attribute("implementationPackage", targetPackage)); } if (targetProject != null) { answer.addAttribute(new Attribute("targetProject", targetProject)); } addPropertyXmlElements(answer); return answer; } @SuppressWarnings({ "rawtypes", "unchecked" }) public void validate(List errors, String contextId) { if (!StringUtility.stringHasValue(getTargetProject())) errors.add(Messages.getString("ValidationError.102", contextId)); if (!StringUtility.stringHasValue(getTargetPackage())) errors.add(Messages.getString("ValidationError.112", "ServiceGenerator", contextId)); if (!StringUtility.stringHasValue(getImplementationPackage())) errors.add(Messages.getString("ValidationError.120", contextId)); }}
7)ConfigurationParserOverride
package run.override.service;import java.io.File;import java.io.FileReader;import java.io.IOException;import java.io.InputStream;import java.io.Reader;import java.util.ArrayList;import java.util.List;import java.util.Properties;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.parsers.ParserConfigurationException;import org.mybatis.generator.config.Configuration;import org.mybatis.generator.config.xml.ConfigurationParser;import org.mybatis.generator.config.xml.MyBatisGeneratorConfigurationParser;import org.mybatis.generator.config.xml.ParserEntityResolver;import org.mybatis.generator.config.xml.ParserErrorHandler;import org.mybatis.generator.exception.XMLParserException;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.xml.sax.InputSource;import org.xml.sax.SAXException;import org.xml.sax.SAXParseException;public class ConfigurationParserOverride extends ConfigurationParser { private List warnings; private List parseErrors; private Properties extraProperties; public ConfigurationParserOverride(List warnings) { this(null, warnings); } public ConfigurationParserOverride(Properties extraProperties, List warnings) { super(extraProperties, warnings); this.extraProperties = extraProperties; if (warnings == null) this.warnings = new ArrayList<>(); else { this.warnings = warnings; } this.parseErrors = new ArrayList<>(); } @Override public Configuration parseConfiguration(File inputFile) throws IOException, XMLParserException { FileReader fr = new FileReader(inputFile); return parseConfiguration(fr); } @Override public Configuration parseConfiguration(InputStream inputStream) throws IOException, XMLParserException { InputSource is = new InputSource(inputStream); return parseConfiguration(is); } @Override public Configuration parseConfiguration(Reader reader) throws IOException, XMLParserException { InputSource is = new InputSource(reader); return parseConfiguration(is); } private Configuration parseConfiguration(InputSource inputSource) throws IOException, XMLParserException { this.parseErrors.clear(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(true); try { DocumentBuilder builder = factory.newDocumentBuilder(); builder.setEntityResolver(new ParserEntityResolver()); ParserErrorHandler handler = new ParserErrorHandler(this.warnings, this.parseErrors); builder.setErrorHandler(handler); Document document = null; try { document = builder.parse(inputSource); } catch (SAXParseException e) { throw new XMLParserException(this.parseErrors); } catch (SAXException e) { if (e.getException() == null) this.parseErrors.add(e.getMessage()); else { this.parseErrors.add(e.getException().getMessage()); } } if (this.parseErrors.size() > 0) { throw new XMLParserException(this.parseErrors); } Element rootNode = document.getDocumentElement(); Configuration config = parseMyBatisGeneratorConfiguration(rootNode); if (this.parseErrors.size() > 0) { throw new XMLParserException(this.parseErrors); } return config; } catch (ParserConfigurationException e) { this.parseErrors.add(e.getMessage()); throw new XMLParserException(this.parseErrors); } } private Configuration parseMyBatisGeneratorConfiguration(Element rootNode) throws XMLParserException { //替换MyBatisGeneratorConfigurationParser MyBatisGeneratorConfigurationParser parser = new MyBatisGeneratorConfigurationParserOverride( this.extraProperties); return parser.parseConfiguration(rootNode); }}
七、PluginChain
通过继承,把以上扩展Plugin串起来(SerializablePlugin
一些项目中可能不需要,故不加入Chain。同时,其他也可以根据需要对Chain进行更改)。
package run.override;import run.override.service.ServiceLayerPlugin;public class PluginChain extends ServiceLayerPlugin {}
八、generatorConfig.xml
增加javaServiceGenerator
相关配置标签。本文使用内部DTD做示例,亦可通过外部DTD或xsd来实现。
1)generatorConfig.xml
] >
九、main启动
package run.generator;import java.io.File;import java.util.ArrayList;import java.util.List;import org.mybatis.generator.api.MyBatisGenerator;import org.mybatis.generator.config.Configuration;import org.mybatis.generator.internal.DefaultShellCallback;import run.override.service.ConfigurationParserOverride;public class Generator { public void generator() throws Exception{ List warnings = new ArrayList(); boolean overwrite = true; File configFile = new File("generatorConfig.xml"); //替换ConfigurationParser ConfigurationParserOverride cp = new ConfigurationParserOverride(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); } public static void main(String[] args) throws Exception { try { Generator generator = new Generator(); generator.generator(); } catch (Exception e) { e.printStackTrace(); } }}
至此,对mybatis-generator的扩展生成代码完成。
生成
代码
坐标
注释
代码生成
参数
序列
页数
页码
个数
同时
不同
内容
字段
对内
总数
数据
数据库
而是
项目
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
互联网科技秀
湖南省网络安全
简单cad软件开发视频
清华大学主页服务器地址
武汉四方博瑞软件开发
虚拟服务器解决方案
网络道德与网络安全初中班会活动
中国网络安全500强企业
良好软件开发市场
数据库国产化替代时间
电脑服务器的辐射
酒店管理系统服务器网络
上海网络安全教育网
大众点评签到数据库
国际服出现服务器未连接怎么办
转播网网络安全
会昌服务器的老板是谁
网络安全问题包括
app可视化开发软件开发
黔西南bim软件开发工程
pes2021怎么连服务器
车辆积分数据库
数据库主外键关系表
虚拟主机支持数据库类型
良好软件开发市场
我有服务器
ao连接不到数据库
2012国家网络安全宣传周主题
惠普服务器配置管理ip
网站服务器安全防护措施