Mybatis-Generator扩展自定义的生成
发表于:2024-11-18 作者:千家信息网编辑
千家信息网最后更新 2024年11月18日,Mybatis-Generator 可自动生成Model、Dao、Mapper代码,但其自带生成的代码存在以下问题:生成的注释不是我们想要的,我们期望的是根据数据库表、字段生成不同的注释;分页代码生成
千家信息网最后更新 2024年11月18日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安全错误
数据库的锁怎样保障安全
益阳串口服务器报价
监听短信数据库变化
获取数据库的年龄
关于登录名和数据库用户
米店吉他谱软件开发
亚马逊服务器搭建ssh
潮州汽车软件开发
互联网科技知识
旧光猫改无线打印服务器
古丈县网络安全执法检查
宁波市镇海有米网络技术有限公司
sql数据库实例在哪里看
携程连接数据库
网络安全恶意代码
数据库连接驱动jar包怎么下载
网络安全方面知识手抄报
软件开发湖南人厉害吗
三菱控制器网络安全配置
我的世界服务器怎么解封所有玩家
大海战为什么登陆不了服务器
ios手机软件开发方案报价
济南多普软件开发有限公司
房山软件开发公司电话
MP4软件开发
http模块制作服务器
服务器怎么屏蔽任务管理
网易一梦江湖官方服务器有哪些
网络技术水平滞后
为什么有网却不能联接服务器
数据库什么叫嵌套查询