mybatis自定义代码生成器(Generator)——自动生成model&dao代码

时间:2023-03-08 21:14:00
mybatis自定义代码生成器(Generator)——自动生成model&dao代码

花了两天的时间研究了下mybatis的generator大体了解了其生成原理以及实现过程。感觉generator做的非常不错,给开发者也留足了空间。看完之后在generator的基础上实现了自定义的生成器。代码start.....

建立了一个maven工程(common)项目结构:

mybatis自定义代码生成器(Generator)——自动生成model&dao代码
----------------------------------------------------------------pom.xml-----------------------------------------------------------
  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>com.yangchao</groupId>
  5. <artifactId>project-common</artifactId>
  6. <version>0.0.1-SNAPSHOT</version>
  7. <name>project-common Maven Webapp</name>
  8. <url>http://maven.apache.org</url>
  9. <dependencies>
  10. <dependency>
  11. <groupId>junit</groupId>
  12. <artifactId>junit</artifactId>
  13. <version>3.8.1</version>
  14. <scope>test</scope>
  15. </dependency>
  16. <dependency>
  17. <groupId>javax</groupId>
  18. <artifactId>javaee-api</artifactId>
  19. <version>7.0</version>
  20. </dependency>
  21. <!-- https://mvnrepository.com/artifact/org.compass-project/compass -->
  22. <dependency>
  23. <groupId>org.compass-project</groupId>
  24. <artifactId>compass</artifactId>
  25. <version>2.0.2</version>
  26. </dependency>
  27. <!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
  28. <dependency>
  29. <groupId>org.mybatis.generator</groupId>
  30. <artifactId>mybatis-generator-core</artifactId>
  31. <version>1.3.2</version>
  32. </dependency>
  33. </dependencies>
  34. </project>

-------------------------------------------------------------------jdbc.properties--------------------------------------------------------------------

  1. jdbc.driver=com.mysql.jdbc.Driver
  2. jdbc.url=jdbc:mysql://localhost:3306/demo1
  3. jdbc.username=root
  4. jdbc.password=root
  5. initialSize=0
  6. maxActive=20
  7. maxIdle=20
  8. minIdle=1
  9. maxWait=60000

--------------------------------------------------------------------generatorConfig.xml--------------------------------------------------------------------------------------

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
  3. <generatorConfiguration>
  4. <!--加载属性文件 -->
  5. <properties resource="jdbc.properties" />
  6. <context id="context1" targetRuntime="MyBatis3">
  7. <!-- 实现自定义的代码生成器plugin -->
  8. <plugin type="mybatis.PaginationPlugin" />
  9. <commentGenerator>
  10. <property name="suppressDate" value="true" />
  11. <!-- 是否去除自动生成的注释 true:是 : false:否 -->
  12. <property name="suppressAllComments" value="true" />
  13. </commentGenerator>
  14. <!-- 数据库连接URL,用户名,密码 -->
  15. <jdbcConnection driverClass="${jdbc.driver}" connectionURL="${jdbc.url}" userId="${jdbc.username}"
  16. password="${jdbc.password}" />
  17. <!--生成模型的包名和位置 -->
  18. <javaModelGenerator targetPackage="common.model" targetProject="project-common/src/main/java/" />
  19. <!--映射文件的包名和位置 -->
  20. <sqlMapGenerator targetPackage="common.model" targetProject="project-common/src/main/java/" />
  21. <!--DAO的包名和位置 -->
  22. <javaClientGenerator targetPackage="common.dao" targetProject="project-common/src/main/java" type="XMLMAPPER" />
  23. <!--要生成哪些表 -->
  24. <table tableName="%" enableSelectByExample="false" enableDeleteByExample="false"
  25. enableCountByExample="false" enableUpdateByExample="false"
  26. selectByExampleQueryId="false">
  27. <property name="rootClass" value="common.BaseEntity" />
  28. </table>
  29. </context>
  30. </generatorConfiguration>

-------------------------------------------------------PaginationPlugin.java------------------------------------------------------

  1. /**
  2. * @项目名称:project-common
  3. * @类名称:PaginationPlugin
  4. * @类描述:自定义代码生成器
  5. * @创建人:YangChao
  6. * @作者单位:北京宝库在线网络技术有限公司
  7. * @联系方式:YangChao@baoku.com
  8. * @创建时间:2016年9月5日 下午3:14:38
  9. * @version 1.0.0
  10. */
  11. public class PaginationPlugin extends PluginAdapter {
  12. /**
  13. * 生成dao
  14. */
  15. @Override
  16. public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
  17. FullyQualifiedJavaType fqjt = new FullyQualifiedJavaType("BaseDao<" + introspectedTable.getBaseRecordType()  + ">");
  18. FullyQualifiedJavaType imp = new FullyQualifiedJavaType("common.BaseDao");
  19. interfaze.addSuperInterface(fqjt);// 添加 extends BaseDao<User>
  20. interfaze.addImportedType(imp);// 添加import common.BaseDao;
  21. interfaze.getMethods().clear();
  22. return true;
  23. }
  24. /**
  25. * 生成实体中每个属性
  26. */
  27. @Override
  28. public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass,
  29. IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
  30. return true;
  31. }
  32. /**
  33. * 生成实体
  34. */
  35. @Override
  36. public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
  37. addSerialVersionUID(topLevelClass, introspectedTable);
  38. return super.modelBaseRecordClassGenerated(topLevelClass, introspectedTable);
  39. }
  40. /**
  41. * 生成mapping
  42. */
  43. @Override
  44. public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) {
  45. return super.sqlMapGenerated(sqlMap, introspectedTable);
  46. }
  47. /**
  48. * 生成mapping 添加自定义sql
  49. */
  50. @Override
  51. public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
  52. String tableName = introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime();// 数据库表名
  53. List<IntrospectedColumn> columns = introspectedTable.getAllColumns();
  54. XmlElement parentElement = document.getRootElement();
  55. // 添加sql——where
  56. XmlElement sql = new XmlElement("sql");
  57. sql.addAttribute(new Attribute("id", "sql_where"));
  58. XmlElement where = new XmlElement("where");
  59. StringBuilder sb = new StringBuilder();
  60. for (IntrospectedColumn introspectedColumn : introspectedTable.getNonPrimaryKeyColumns()) {
  61. XmlElement isNotNullElement = new XmlElement("if"); //$NON-NLS-1$
  62. sb.setLength(0);
  63. sb.append(introspectedColumn.getJavaProperty());
  64. sb.append(" != null"); //$NON-NLS-1$
  65. isNotNullElement.addAttribute(new Attribute("test", sb.toString())); //$NON-NLS-1$
  66. where.addElement(isNotNullElement);
  67. sb.setLength(0);
  68. sb.append(" and ");
  69. sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
  70. sb.append(" = "); //$NON-NLS-1$
  71. sb.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn));
  72. isNotNullElement.addElement(new TextElement(sb.toString()));
  73. }
  74. sql.addElement(where);
  75. parentElement.addElement(sql);
  76. //添加getList
  77. XmlElement select = new XmlElement("select");
  78. select.addAttribute(new Attribute("id", "getList"));
  79. select.addAttribute(new Attribute("resultMap", "BaseResultMap"));
  80. select.addAttribute(new Attribute("parameterType", introspectedTable.getBaseRecordType()));
  81. select.addElement(new TextElement(" select * from "+ introspectedTable.getFullyQualifiedTableNameAtRuntime()));
  82. XmlElement include = new XmlElement("include");
  83. include.addAttribute(new Attribute("refid", "sql_where"));
  84. select.addElement(include);
  85. parentElement.addElement(select);
  86. return super.sqlMapDocumentGenerated(document, introspectedTable);
  87. }
  88. @Override
  89. public boolean sqlMapUpdateByPrimaryKeyWithoutBLOBsElementGenerated(XmlElement element,
  90. IntrospectedTable introspectedTable) {
  91. return false;
  92. }
  93. @Override
  94. public boolean sqlMapInsertElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
  95. return false;
  96. }
  97. @Override
  98. public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(XmlElement element,
  99. IntrospectedTable introspectedTable) {
  100. // LIMIT5,10; // 检索记录行 6-15
  101. //      XmlElement isNotNullElement = new XmlElement("if");//$NON-NLS-1$
  102. //      isNotNullElement.addAttribute(new Attribute("test", "limitStart != null and limitStart >=0"));//$NON-NLS-1$ //$NON-NLS-2$
  103. // isNotNullElement.addElement(new
  104. // TextElement("limit ${limitStart} , ${limitEnd}"));
  105. // element.addElement(isNotNullElement);
  106. // LIMIT 5;//检索前 5个记录行
  107. return super.sqlMapSelectByExampleWithoutBLOBsElementGenerated(element, introspectedTable);
  108. }
  109. /**
  110. * mapping中添加方法
  111. */
  112. // @Override
  113. public boolean sqlMapDocumentGenerated2(Document document, IntrospectedTable introspectedTable) {
  114. String tableName = introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime();// 数据库表名
  115. List<IntrospectedColumn> columns = introspectedTable.getAllColumns();
  116. // 添加sql
  117. XmlElement sql = new XmlElement("select");
  118. XmlElement parentElement = document.getRootElement();
  119. XmlElement deleteLogicByIdsElement = new XmlElement("update");
  120. deleteLogicByIdsElement.addAttribute(new Attribute("id", "deleteLogicByIds"));
  121. deleteLogicByIdsElement
  122. .addElement(new TextElement(
  123. "update "
  124. + tableName
  125. + " set deleteFlag = #{deleteFlag,jdbcType=INTEGER} where id in "
  126. + " <foreach item=\"item\" index=\"index\" collection=\"ids\" open=\"(\" separator=\",\" close=\")\">#{item}</foreach> "));
  127. parentElement.addElement(deleteLogicByIdsElement);
  128. XmlElement queryPage = new XmlElement("select");
  129. queryPage.addAttribute(new Attribute("id", "queryPage"));
  130. queryPage.addAttribute(new Attribute("resultMap", "BaseResultMap"));
  131. queryPage.addElement(new TextElement("select "));
  132. XmlElement include = new XmlElement("include");
  133. include.addAttribute(new Attribute("refid", "Base_Column_List"));
  134. queryPage.addElement(include);
  135. queryPage.addElement(new TextElement(" from " + tableName + " ${sql}"));
  136. parentElement.addElement(queryPage);
  137. return super.sqlMapDocumentGenerated(document, introspectedTable);
  138. }
  139. private void addSerialVersionUID(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
  140. CommentGenerator commentGenerator = context.getCommentGenerator();
  141. Field field = new Field();
  142. field.setVisibility(JavaVisibility.PRIVATE);
  143. field.setType(new FullyQualifiedJavaType("long"));
  144. field.setStatic(true);
  145. field.setFinal(true);
  146. field.setName("serialVersionUID");
  147. field.setInitializationString("1L");
  148. commentGenerator.addFieldComment(field, introspectedTable);
  149. topLevelClass.addField(field);
  150. }
  151. /*
  152. * Dao中添加方法
  153. */
  154. private Method generateDeleteLogicByIds(Method method, IntrospectedTable introspectedTable) {
  155. Method m = new Method("deleteLogicByIds");
  156. m.setVisibility(method.getVisibility());
  157. m.setReturnType(FullyQualifiedJavaType.getIntInstance());
  158. m.addParameter(new Parameter(FullyQualifiedJavaType.getIntInstance(), "deleteFlag", "@Param(\"deleteFlag\")"));
  159. m.addParameter(new Parameter(new FullyQualifiedJavaType("Integer[]"), "ids", "@Param(\"ids\")"));
  160. context.getCommentGenerator().addGeneralMethodComment(m, introspectedTable);
  161. return m;
  162. }
  163. /*
  164. * 实体中添加属性
  165. */
  166. private void addLimit(TopLevelClass topLevelClass, IntrospectedTable introspectedTable, String name) {
  167. CommentGenerator commentGenerator = context.getCommentGenerator();
  168. Field field = new Field();
  169. field.setVisibility(JavaVisibility.PROTECTED);
  170. field.setType(FullyQualifiedJavaType.getIntInstance());
  171. field.setName(name);
  172. field.setInitializationString("-1");
  173. commentGenerator.addFieldComment(field, introspectedTable);
  174. topLevelClass.addField(field);
  175. char c = name.charAt(0);
  176. String camel = Character.toUpperCase(c) + name.substring(1);
  177. Method method = new Method();
  178. method.setVisibility(JavaVisibility.PUBLIC);
  179. method.setName("set" + camel);
  180. method.addParameter(new Parameter(FullyQualifiedJavaType.getIntInstance(), name));
  181. method.addBodyLine("this." + name + "=" + name + ";");
  182. commentGenerator.addGeneralMethodComment(method, introspectedTable);
  183. topLevelClass.addMethod(method);
  184. method = new Method();
  185. method.setVisibility(JavaVisibility.PUBLIC);
  186. method.setReturnType(FullyQualifiedJavaType.getIntInstance());
  187. method.setName("get" + camel);
  188. method.addBodyLine("return " + name + ";");
  189. commentGenerator.addGeneralMethodComment(method, introspectedTable);
  190. topLevelClass.addMethod(method);
  191. }
  192. public boolean validate(List<String> arg0) {
  193. return true;
  194. }
  195. public static void generate() {
  196. String config = PaginationPlugin.class.getClassLoader().getResource("mybatisConfig.xml").getFile();
  197. String[] arg = { "-configfile", config, "-overwrite" };
  198. ShellRunner.main(arg);
  199. }
  200. public static void main(String[] args) {
  201. generate();
  202. }
  203. }

------------------------------------------------BaseDao.java--------------------------------------------
  1. /**
  2. * @项目名称:project-common
  3. * @类名称:BaseDao
  4. * @类描述:
  5. * @创建人:YangChao
  6. * @作者单位:北京宝库在线网络技术有限公司
  7. * @联系方式:YangChao@baoku.com
  8. * @创建时间:2016年9月5日 下午2:51:19
  9. * @version 1.0.0
  10. */
  11. public interface BaseDao<T> {
  12. public T selectByPrimaryKey(Integer id);
  13. public int deleteByPrimaryKey(Integer id);
  14. public int insertSelective(T t);
  15. public int updateByPrimaryKeySelective(T t);
  16. public List<T> getList(T t);
  17. // 获取数量
  18. public int getCountSelective(T t);
  19. /**
  20. *
  21. * @Title: findPage
  22. * @Description: TODO()
  23. * @param page
  24. *            分页参数
  25. * @param sql
  26. *            mybatis sql语句
  27. * @param values
  28. *            命名参数,按名称绑定
  29. * @return 分页查询结果, 附带结果列表及所有查询时的参数.
  30. * @author YangChao
  31. * @date 2016年9月7日 下午5:30:28
  32. */
  33. public PageView<T> findPage(final PageView<T> page, final String sql, final Map<String, Object> values);
  34. }

-------------------------------------------------BaseEntity.java---------------------------------------------------
  1. /**
  2. * @项目名称:project-common
  3. * @类名称:BaseEntity
  4. * @类描述:所有实体类的父类。可将公共的属性所有类序列化集中在此类中
  5. * @创建人:YangChao
  6. * @作者单位:北京宝库在线网络技术有限公司
  7. * @联系方式:YangChao@baoku.com
  8. * @创建时间:2016年9月5日 上午11:37:02
  9. * @version 1.0.0
  10. */
  11. public abstract class BaseEntity implements Serializable {
  12. private static final long serialVersionUID = 1L;
  13. private Integer id;
  14. public Integer getId() {
  15. return id;
  16. }
  17. public void setId(Integer id) {
  18. this.id = id;
  19. }
  20. }

---------------------------------------------------------------------------------最终生成dao&&model------------------------------------------------------------------------------------------------

--dao--
UserMapper.java:
  1. package common.dao;
  2. import common.BaseDao;
  3. import common.model.User;
  4. public interface UserMapper extends BaseDao<User> {
  5. }

---model---

User.java
  1. package common.model;
  2. import common.BaseEntity;
  3. public class User extends BaseEntity {
  4. private Integer accountId;
  5. private String loginname;
  6. private String password;
  7. private Integer status;
  8. private static final long serialVersionUID = 1L;
  9. public Integer getAccountId() {
  10. return accountId;
  11. }
  12. public void setAccountId(Integer accountId) {
  13. this.accountId = accountId;
  14. }
  15. public String getLoginname() {
  16. return loginname;
  17. }
  18. public void setLoginname(String loginname) {
  19. this.loginname = loginname;
  20. }
  21. public String getPassword() {
  22. return password;
  23. }
  24. public void setPassword(String password) {
  25. this.password = password;
  26. }
  27. public Integer getStatus() {
  28. return status;
  29. }
  30. public void setStatus(Integer status) {
  31. this.status = status;
  32. }
  33. }

UserMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  3. <mapper namespace="common.dao.UserMapper" >
  4. <resultMap id="BaseResultMap" type="common.model.User" >
  5. <id column="id" property="id" jdbcType="INTEGER" />
  6. <result column="account_id" property="accountId" jdbcType="INTEGER" />
  7. <result column="loginname" property="loginname" jdbcType="VARCHAR" />
  8. <result column="password" property="password" jdbcType="VARCHAR" />
  9. <result column="status" property="status" jdbcType="INTEGER" />
  10. </resultMap>
  11. <sql id="Base_Column_List" >
  12. id, account_id, loginname, password, status
  13. </sql>
  14. <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
  15. select
  16. <include refid="Base_Column_List" />
  17. from user
  18. where id = #{id,jdbcType=INTEGER}
  19. </select>
  20. <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
  21. delete from user
  22. where id = #{id,jdbcType=INTEGER}
  23. </delete>
  24. <insert id="insertSelective" parameterType="common.model.User" >
  25. insert into user
  26. <trim prefix="(" suffix=")" suffixOverrides="," >
  27. <if test="id != null" >
  28. id,
  29. </if>
  30. <if test="accountId != null" >
  31. account_id,
  32. </if>
  33. <if test="loginname != null" >
  34. loginname,
  35. </if>
  36. <if test="password != null" >
  37. password,
  38. </if>
  39. <if test="status != null" >
  40. status,
  41. </if>
  42. </trim>
  43. <trim prefix="values (" suffix=")" suffixOverrides="," >
  44. <if test="id != null" >
  45. #{id,jdbcType=INTEGER},
  46. </if>
  47. <if test="accountId != null" >
  48. #{accountId,jdbcType=INTEGER},
  49. </if>
  50. <if test="loginname != null" >
  51. #{loginname,jdbcType=VARCHAR},
  52. </if>
  53. <if test="password != null" >
  54. #{password,jdbcType=VARCHAR},
  55. </if>
  56. <if test="status != null" >
  57. #{status,jdbcType=INTEGER},
  58. </if>
  59. </trim>
  60. </insert>
  61. <update id="updateByPrimaryKeySelective" parameterType="common.model.User" >
  62. update user
  63. <set >
  64. <if test="accountId != null" >
  65. account_id = #{accountId,jdbcType=INTEGER},
  66. </if>
  67. <if test="loginname != null" >
  68. loginname = #{loginname,jdbcType=VARCHAR},
  69. </if>
  70. <if test="password != null" >
  71. password = #{password,jdbcType=VARCHAR},
  72. </if>
  73. <if test="status != null" >
  74. status = #{status,jdbcType=INTEGER},
  75. </if>
  76. </set>
  77. where id = #{id,jdbcType=INTEGER}
  78. </update>
  79. <sql id="sql_where" >
  80. <where >
  81. <if test="accountId != null" >
  82. and account_id = #{accountId,jdbcType=INTEGER}
  83. </if>
  84. <if test="loginname != null" >
  85. and loginname = #{loginname,jdbcType=VARCHAR}
  86. </if>
  87. <if test="password != null" >
  88. and password = #{password,jdbcType=VARCHAR}
  89. </if>
  90. <if test="status != null" >
  91. and status = #{status,jdbcType=INTEGER}
  92. </if>
  93. </where>
  94. </sql>
  95. <select id="getList" resultMap="BaseResultMap" parameterType="common.model.User" >
  96. select * from user
  97. <include refid="sql_where" />
  98. </select>
  99. </mapper>

-----------------------------------代码end------------------------------------
心得:由于开始使用原始的generator生成代码存在,生成后的代码继承结构不存在,重复性代码过多。其实生成所有的代码都是可自定义的,在此我只是将dao中所有的crud方法提取出去放到BaseDao中,以方便之后在具体的dao中添加特殊的需求,让代码简单明了。