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

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

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




----------------------------------------------------------------pom.xml-----------------------------------------------------------

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.yangchao</groupId>
	<artifactId>project-common</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>project-common Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>javax</groupId>
			<artifactId>javaee-api</artifactId>
			<version>7.0</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.compass-project/compass -->
		<dependency>
			<groupId>org.compass-project</groupId>
			<artifactId>compass</artifactId>
			<version>2.0.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
		<dependency>
			<groupId>org.mybatis.generator</groupId>
			<artifactId>mybatis-generator-core</artifactId>
			<version>1.3.2</version>
		</dependency>

	</dependencies>
</project>


-------------------------------------------------------------------jdbc.properties--------------------------------------------------------------------
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/demo1
jdbc.username=root
jdbc.password=root
initialSize=0
maxActive=20
maxIdle=20
minIdle=1
maxWait=60000

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

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

/**
 * @项目名称:project-common
 * @类名称:PaginationPlugin
 * @类描述:自定义代码生成器
 * @创建人:YangChao
 * @作者单位:北京宝库在线网络技术有限公司
 * @联系方式:YangChao@baoku.com
 * @创建时间:2016年9月5日 下午3:14:38
 * @version 1.0.0
 */
public class PaginationPlugin extends PluginAdapter {
	/**
	 * 生成dao
	 */
	@Override
	public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
		FullyQualifiedJavaType fqjt = new FullyQualifiedJavaType("BaseDao<" + introspectedTable.getBaseRecordType()	+ ">");
		FullyQualifiedJavaType imp = new FullyQualifiedJavaType("common.BaseDao");
		interfaze.addSuperInterface(fqjt);// 添加 extends BaseDao<User>
		interfaze.addImportedType(imp);// 添加import common.BaseDao;
		interfaze.getMethods().clear();
		return true;
	}

	/**
	 * 生成实体中每个属性
	 */
	@Override
	public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass,
			IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
		return true;
	}

	/**
	 * 生成实体
	 */
	@Override
	public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
		addSerialVersionUID(topLevelClass, introspectedTable);
		return super.modelBaseRecordClassGenerated(topLevelClass, introspectedTable);
	}

	/**
	 * 生成mapping
	 */
	@Override
	public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) {
		return super.sqlMapGenerated(sqlMap, introspectedTable);
	}

	/**
	 * 生成mapping 添加自定义sql
	 */
	@Override
	public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
		String tableName = introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime();// 数据库表名
		List<IntrospectedColumn> columns = introspectedTable.getAllColumns();
		XmlElement parentElement = document.getRootElement();
		
		// 添加sql——where
		XmlElement sql = new XmlElement("sql");
		sql.addAttribute(new Attribute("id", "sql_where"));
		XmlElement where = new XmlElement("where");
		StringBuilder sb = new StringBuilder();
		for (IntrospectedColumn introspectedColumn : introspectedTable.getNonPrimaryKeyColumns()) {
            XmlElement isNotNullElement = new XmlElement("if"); //$NON-NLS-1$
            sb.setLength(0);
            sb.append(introspectedColumn.getJavaProperty());
            sb.append(" != null"); //$NON-NLS-1$
            isNotNullElement.addAttribute(new Attribute("test", sb.toString())); //$NON-NLS-1$
            where.addElement(isNotNullElement);

            sb.setLength(0);
            sb.append(" and ");
            sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            sb.append(" = "); //$NON-NLS-1$
            sb.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn));
            isNotNullElement.addElement(new TextElement(sb.toString()));
        }
		sql.addElement(where);
		parentElement.addElement(sql);
		
		//添加getList
		XmlElement select = new XmlElement("select");
		select.addAttribute(new Attribute("id", "getList"));
		select.addAttribute(new Attribute("resultMap", "BaseResultMap"));
		select.addAttribute(new Attribute("parameterType", introspectedTable.getBaseRecordType()));
		select.addElement(new TextElement(" select * from "+ introspectedTable.getFullyQualifiedTableNameAtRuntime()));
		
		XmlElement include = new XmlElement("include");
		include.addAttribute(new Attribute("refid", "sql_where"));
		
		select.addElement(include);
		parentElement.addElement(select);
		
		return super.sqlMapDocumentGenerated(document, introspectedTable);
	}

	@Override
	public boolean sqlMapUpdateByPrimaryKeyWithoutBLOBsElementGenerated(XmlElement element,
			IntrospectedTable introspectedTable) {
		return false;
	}

	@Override
	public boolean sqlMapInsertElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
		return false;
	}

	@Override
	public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(XmlElement element,
			IntrospectedTable introspectedTable) {
		// LIMIT5,10; // 检索记录行 6-15
		//		XmlElement isNotNullElement = new XmlElement("if");//$NON-NLS-1$
		//		isNotNullElement.addAttribute(new Attribute("test", "limitStart != null and limitStart >=0"));//$NON-NLS-1$ //$NON-NLS-2$
		// isNotNullElement.addElement(new
		// TextElement("limit ${limitStart} , ${limitEnd}"));
		// element.addElement(isNotNullElement);
		// LIMIT 5;//检索前 5个记录行
		return super.sqlMapSelectByExampleWithoutBLOBsElementGenerated(element, introspectedTable);
	}

	/**
	 * mapping中添加方法
	 */
	// @Override
	public boolean sqlMapDocumentGenerated2(Document document, IntrospectedTable introspectedTable) {
		String tableName = introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime();// 数据库表名
		List<IntrospectedColumn> columns = introspectedTable.getAllColumns();
		// 添加sql
		XmlElement sql = new XmlElement("select");

		XmlElement parentElement = document.getRootElement();
		XmlElement deleteLogicByIdsElement = new XmlElement("update");
		deleteLogicByIdsElement.addAttribute(new Attribute("id", "deleteLogicByIds"));
		deleteLogicByIdsElement
				.addElement(new TextElement(
						"update "
								+ tableName
								+ " set deleteFlag = #{deleteFlag,jdbcType=INTEGER} where id in "
								+ " <foreach item=\"item\" index=\"index\" collection=\"ids\" open=\"(\" separator=\",\" close=\")\">#{item}</foreach> "));

		parentElement.addElement(deleteLogicByIdsElement);
		XmlElement queryPage = new XmlElement("select");
		queryPage.addAttribute(new Attribute("id", "queryPage"));
		queryPage.addAttribute(new Attribute("resultMap", "BaseResultMap"));
		queryPage.addElement(new TextElement("select "));

		XmlElement include = new XmlElement("include");
		include.addAttribute(new Attribute("refid", "Base_Column_List"));

		queryPage.addElement(include);
		queryPage.addElement(new TextElement(" from " + tableName + " ${sql}"));
		parentElement.addElement(queryPage);
		return super.sqlMapDocumentGenerated(document, introspectedTable);
	}

	private void addSerialVersionUID(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
		CommentGenerator commentGenerator = context.getCommentGenerator();
		Field field = new Field();
		field.setVisibility(JavaVisibility.PRIVATE);
		field.setType(new FullyQualifiedJavaType("long"));
		field.setStatic(true);
		field.setFinal(true);
		field.setName("serialVersionUID");
		field.setInitializationString("1L");
		commentGenerator.addFieldComment(field, introspectedTable);
		topLevelClass.addField(field);
	}

	/*
	 * Dao中添加方法
	 */
	private Method generateDeleteLogicByIds(Method method, IntrospectedTable introspectedTable) {
		Method m = new Method("deleteLogicByIds");
		m.setVisibility(method.getVisibility());
		m.setReturnType(FullyQualifiedJavaType.getIntInstance());
		m.addParameter(new Parameter(FullyQualifiedJavaType.getIntInstance(), "deleteFlag", "@Param(\"deleteFlag\")"));
		m.addParameter(new Parameter(new FullyQualifiedJavaType("Integer[]"), "ids", "@Param(\"ids\")"));
		context.getCommentGenerator().addGeneralMethodComment(m, introspectedTable);
		return m;
	}

	/*
	 * 实体中添加属性
	 */
	private void addLimit(TopLevelClass topLevelClass, IntrospectedTable introspectedTable, String name) {
		CommentGenerator commentGenerator = context.getCommentGenerator();
		Field field = new Field();
		field.setVisibility(JavaVisibility.PROTECTED);
		field.setType(FullyQualifiedJavaType.getIntInstance());
		field.setName(name);
		field.setInitializationString("-1");
		commentGenerator.addFieldComment(field, introspectedTable);
		topLevelClass.addField(field);
		char c = name.charAt(0);
		String camel = Character.toUpperCase(c) + name.substring(1);
		Method method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setName("set" + camel);
		method.addParameter(new Parameter(FullyQualifiedJavaType.getIntInstance(), name));
		method.addBodyLine("this." + name + "=" + name + ";");
		commentGenerator.addGeneralMethodComment(method, introspectedTable);
		topLevelClass.addMethod(method);
		method = new Method();
		method.setVisibility(JavaVisibility.PUBLIC);
		method.setReturnType(FullyQualifiedJavaType.getIntInstance());
		method.setName("get" + camel);
		method.addBodyLine("return " + name + ";");
		commentGenerator.addGeneralMethodComment(method, introspectedTable);
		topLevelClass.addMethod(method);
	}

	public boolean validate(List<String> arg0) {
		return true;
	}

	public static void generate() {
		String config = PaginationPlugin.class.getClassLoader().getResource("mybatisConfig.xml").getFile();
		String[] arg = { "-configfile", config, "-overwrite" };
		ShellRunner.main(arg);
	}

	public static void main(String[] args) {
		generate();
	}
}


------------------------------------------------BaseDao.java--------------------------------------------
/**
 * @项目名称:project-common
 * @类名称:BaseDao
 * @类描述:
 * @创建人:YangChao
 * @作者单位:北京宝库在线网络技术有限公司
 * @联系方式:YangChao@baoku.com
 * @创建时间:2016年9月5日 下午2:51:19
 * @version 1.0.0
 */
public interface BaseDao<T> {
	public T selectByPrimaryKey(Integer id);

	public int deleteByPrimaryKey(Integer id);

	public int insertSelective(T t);

	public int updateByPrimaryKeySelective(T t);

	public List<T> getList(T t);

	// 获取数量
	public int getCountSelective(T t);

	/**
	 * 
	 * @Title: findPage
	 * @Description: TODO()
	 * @param page
	 *            分页参数
	 * @param sql
	 *            mybatis sql语句
	 * @param values
	 *            命名参数,按名称绑定
	 * @return 分页查询结果, 附带结果列表及所有查询时的参数.
	 * @author YangChao
	 * @date 2016年9月7日 下午5:30:28
	 */
	public PageView<T> findPage(final PageView<T> page, final String sql, final Map<String, Object> values);
}


-------------------------------------------------BaseEntity.java---------------------------------------------------
/**
 * @项目名称:project-common
 * @类名称:BaseEntity
 * @类描述:所有实体类的父类。可将公共的属性所有类序列化集中在此类中
 * @创建人:YangChao
 * @作者单位:北京宝库在线网络技术有限公司
 * @联系方式:YangChao@baoku.com
 * @创建时间:2016年9月5日 上午11:37:02
 * @version 1.0.0
 */
public abstract class BaseEntity implements Serializable {
	private static final long serialVersionUID = 1L;
	private Integer id;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

}

---------------------------------------------------------------------------------最终生成dao&&model------------------------------------------------------------------------------------------------
--dao--
UserMapper.java:

package common.dao;

import common.BaseDao;
import common.model.User;

public interface UserMapper extends BaseDao<User> {
}

---model---
User.java

package common.model;

import common.BaseEntity;

public class User extends BaseEntity {
    private Integer accountId;

    private String loginname;

    private String password;

    private Integer status;

    private static final long serialVersionUID = 1L;

    public Integer getAccountId() {
        return accountId;
    }

    public void setAccountId(Integer accountId) {
        this.accountId = accountId;
    }

    public String getLoginname() {
        return loginname;
    }

    public void setLoginname(String loginname) {
        this.loginname = loginname;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }
}


UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="common.dao.UserMapper" >
  <resultMap id="BaseResultMap" type="common.model.User" >
    <id column="id" property="id" jdbcType="INTEGER" />
    <result column="account_id" property="accountId" jdbcType="INTEGER" />
    <result column="loginname" property="loginname" jdbcType="VARCHAR" />
    <result column="password" property="password" jdbcType="VARCHAR" />
    <result column="status" property="status" jdbcType="INTEGER" />
  </resultMap>
  <sql id="Base_Column_List" >
    id, account_id, loginname, password, status
  </sql>
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from user
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
    delete from user
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insertSelective" parameterType="common.model.User" >
    insert into user
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        id,
      </if>
      <if test="accountId != null" >
        account_id,
      </if>
      <if test="loginname != null" >
        loginname,
      </if>
      <if test="password != null" >
        password,
      </if>
      <if test="status != null" >
        status,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        #{id,jdbcType=INTEGER},
      </if>
      <if test="accountId != null" >
        #{accountId,jdbcType=INTEGER},
      </if>
      <if test="loginname != null" >
        #{loginname,jdbcType=VARCHAR},
      </if>
      <if test="password != null" >
        #{password,jdbcType=VARCHAR},
      </if>
      <if test="status != null" >
        #{status,jdbcType=INTEGER},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="common.model.User" >
    update user
    <set >
      <if test="accountId != null" >
        account_id = #{accountId,jdbcType=INTEGER},
      </if>
      <if test="loginname != null" >
        loginname = #{loginname,jdbcType=VARCHAR},
      </if>
      <if test="password != null" >
        password = #{password,jdbcType=VARCHAR},
      </if>
      <if test="status != null" >
        status = #{status,jdbcType=INTEGER},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <sql id="sql_where" >
    <where >
      <if test="accountId != null" >
         and account_id = #{accountId,jdbcType=INTEGER}
      </if>
      <if test="loginname != null" >
         and loginname = #{loginname,jdbcType=VARCHAR}
      </if>
      <if test="password != null" >
         and password = #{password,jdbcType=VARCHAR}
      </if>
      <if test="status != null" >
         and status = #{status,jdbcType=INTEGER}
      </if>
    </where>
  </sql>
  <select id="getList" resultMap="BaseResultMap" parameterType="common.model.User" >
     select * from user
    <include refid="sql_where" />
  </select>
</mapper>


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






阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页