您的位置:首页 > 移动开发

MyBatis代码实例系列-08:MyBatisGenerator插件及扩展(中文注释和Mapper重命名为Dao)

2018-02-04 17:00 701 查看
超级通道:MyBatis代码实例系列-绪论

本章主要记录如何使用Mybatis Generator,并在其基础上进行扩展优化,涉及到的技术有:

- MyBatis Generator:MyBatis代码自动生成插件,能够生成实体.java、实体Mapper.java和实体Mapper.xml,注释为英文

- git@github.com:li24361/mybatis-generator-core.git:开源插件,对MyBatis Generator进行了扩展,实现了中文注释,并将生成结果重命名为:实体Entity.java、实体Dao.java和实体Dao.xml。

- generatorConfig.xml:MyBatis Generator的配置文件。

- ToStringPlugin:MyBatis Generator的插件,在实体类中自动生成toString()方法。

- EqualsHashCodePlugin:MyBatis Generator的插件,在实体类中自动添加hashCode()和Equals()方法。

1.MyBatis Generator简介

在使用MyBatis框架进行开发时,每用到一张表就要手动创建实体类、XML映射文件和映射接口,这些都是重复性工作,耗费了我们大量精力。

MyBatis Generator (简称MBG) 是一个Mybatis的代码生成器。它可以根据数据库中的表,生成对应的实体类、XML映射文件和映射接口,节约了大量的时间去开发和业务逻辑有关的功能。

当然,如果是多表联合查询和存储过程,仍然需要手动处理。

2.通过Maven运行 MyBatis Generator

2.1.pom.xml

<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.6</version>
</dependency>

<plugins>
...
<plugin>
<!--MyBatis-generator插件,生成结果:Xxxx.java,XxxxMapper,XxxxMapper.xml,注释为英文-->
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.6</version>
<dependencies>
<!--mysql数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
<configuration>
<!--MyBatis-generator配置文件的位置-->
<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
<!--是否覆盖同名文件,默认为false-->
<overwrite>true</overwrite>
<!--是否将执行过程输出到控制台-->
<verbose>true</verbose>
</configuration>
<!--自动生成-->
<executions>
<execution>
<id>MyBatis Generator</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>


2.2.MyBatis-generator配置文件: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">
<!--MyBatis-generator配置文件:-->
<generatorConfiguration>
<properties resource="jdbc.properties"/>
<!--context:指定生成环境-->
<!--targetRuntime="MyBatis3Simple":生成兼容MyBatis 3.0或更高版本,但不会有"by example"一类的方法,只有少量的动态SQL。-->
<!--defaultModelType="flat":每一张表只生成一个实体类。这个实体类包含表中的所有字段。-->
<context id="MysqlContext" targetRuntime="MyBatis3Simple" defaultModelType="flat">

<!--beginningDelimiter和endingDelimiter:自动分割包含空格的SQL标识符,在MySql中使用`-->
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>

<!--生成的java对象模型自动添加toString()方法-->
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
<!--生成的java对象模型自动添加hashCode()和Equals()方法-->
<plugin type="org.mybatis.generator.plugins.EqualsHashCodePlugin"/>

<!--注释生成配置-->
<!--原始版本:注释为英文,生成结果:Xxxx.java,XxxxMapper,XxxxMapper.xml,-->
<commentGenerator>
<!--是否抑制所有的注释,默认为false-->
<property name="suppressAllComments" value="false"/>
<!--是否抑制注释中的时间,默认为false,这里改为true,不生成时间(如果生成时间,则每次都是新版本,每次都要提交)-->
<property name="suppressDate" value="true"/>
</commentGenerator>

<!--数据库连接属性-->
<jdbcConnection driverClass="${jdbc.driverClassName}"
connectionURL="${jdbc.url}"
userId="${jdbc.username}"
password="${jdbc.password}">
</jdbcConnection>

<!--Java实体类生成配置-->
<!--targetPackage:生成的实体类存放的包名-->
<!--targetProject:目标项目路径(这里是相对路径,也可以绝对路径)-->
<javaModelGenerator targetPackage="pers.hanchao.himybatis.generator.entity" targetProject="src\main\java">
<!--是否允许建立子包,generator能够通过mysql的schema再生成一级子目录,默认为false-->
<property name="enableSubPackages" value="true"/>
<!--是否对查询结果进行trim()操作,例如username.trim(),默认为false-->
<property name="trimStrings" value="true" />
</javaModelGenerator>

<!--XML映射文件配置-->
<!--targetPackage:生成的XML映射文件的包名-->
<!--targetProject:目标项目路径(这里是相对路径,也可以绝对路径)-->
<sqlMapGenerator targetPackage="generator"  targetProject="src\main\resources">
<!--是否允许建立子包,generator能够通过mysql的schema再生成一级子目录,默认为false-->
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>

<!--Java 客户端代码生成配置,即IDAO配置-->
<!--type="XMLMAPPER":生成的对象是 MyBatis 3.x 映射器基础结构的 Java接口。 这些接口将会依赖于生成的XML文件。-->
<!--targetPackage:用于存放IDAO-->
<!--targetProject:目标项目路径(这里是相对路径,也可以绝对路径)-->
<javaClientGenerator type="XMLMAPPER" targetPackage="pers.hanchao.himybatis.generator.dao" targetProject="src\main\java">
<!--是否允许建立子包,generator能够通过mysql的schema再生成一级子目录,默认为false-->
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>

<!--配置生成哪些表、哪些主键-->
<!--schema="exam":指定schema-->
<!--tableName="%":生成全部表-->
<!--<table schema="exam" tableName="%">-->
<table schema="exam" tableName="topic">
<!--generatedKey:指定自动生成主键的属性-->
<!--column="id":凡是列名为id的,都生成为主键-->
<!--sqlStatement="Mysql":insert表时主键转换为SELECT LAST_INSERT_ID()-->
<generatedKey column="id" sqlStatement="Mysql"/>
</table>
</context>
</generatorConfiguration>


2.3.运行MyBatis Generator

IDEA
中,点击
Edit Configurations


–>添加一个
Maven
配置

–>录入
Name


–>Command Line录入:mybatis-generator:generate

–>点击
OK
保存配置

–>点击或通过
Alt+Shift+X
运行这个
Maven
配置

2.4.生成结果

生成目录如下:

src
\---main
\---java
|   \---pers
|       \---hanchao
|           \---himybatis
|               \---generator
|                   \---dao
|                   |   \---TopicMapper.java
|                   |---entity
|                       \---Topic.java
\---webapp
\---generator
\---TopicMapper.xml


代码展示:

Topic.java

只详细展示第一个字段,后续字段和方法略。

package pers.hanchao.himybatis.generator.entity;

public class Topic {
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column topic.id
*
* @mbg.generated
*/
private Integer id;

//other field

//setter getter toString hashCode equals
}


TopicMapper.java

只详细展示第一个方法,后续方法略。

package pers.hanchao.himybatis.generator.dao;

import java.util.List;
import pers.hanchao.himybatis.generator.entity.Topic;

public interface TopicMapper {
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table topic
*
* @mbg.generated
*/
int deleteByPrimaryKey(Integer id);

//int insert(Topic record);
//Topic selectByPrimaryKey(Integer id);
//List<Topic> selectAll();
//int updateByPrimaryKey(Topic record);
}


TopicMapper.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="pers.hanchao.himybatis.generator.dao.TopicMapper">
<resultMap id="BaseResultMap" type="pers.hanchao.himybatis.generator.entity.Topic">
<!--
WARNING - @mbg.generated
This element is automatically generated by MyBatis Generator, do not modify.
-->
<id column="id" jdbcType="INTEGER" property="id" />
<result column="title" jdbcType="VARCHAR" property="title" />
<result column="score" jdbcType="INTEGER" property="score" />
<result column="answer" jdbcType="VARCHAR" property="answer" />
</resultMap>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
<!--
WARNING - @mbg.generated
This element is automatically generated by MyBatis Generator, do not modify.
-->
delete from topic
where id = #{id,jdbcType=INTEGER}
</delete>
<!--
<insert id="insert" ...
<update id="updateByPrimaryKey" ...
<select id="selectByPrimaryKey" ...
<select id="selectAll" ...
-->
</mapper>


有待改进之处:

生成的Topic.java和TopicMapper.java中的注释都是英文的,尤其是Topic.java的字段注释。这样对实际开发很不友好,还需要手动将所有的注释改为中文,不仅浪费时间,而且容易出错。

我喜欢将实体Mapper重命名为XxxxDao.java或者XxxxIDAO,而非XxxxMapper.java,所以还需要手动将
XxxxMapper
全部修改为
XxxxDao


3.扩展MyBatis Generator

鉴于以上原因,很多大牛们通过修改MyBatis Generator源码或者新增实现类,提供了各种各样的解决方案。

本章只详细介绍其中的一种方案:由
li24361
提供的https://github.com/li24361/mybatis-generator-core

3.1.git clone

mybatis-generator-core
项目克隆到本地

git clone git@github.com:li24361/mybatis-generator-core.git


3.2.打成jar包到本地Repository

mybatis-generator-core
打成jar包并存放到本地仓库中

cd mybatis-generator-core/

mvn install -Dmaven.test.skip=true


3.3.修改pom.xml

注意:mybatis-generator-maven-plugin的版本号是1.3.2

<plugin>
<!--MyBatis-generator插件,生成结果:Xxxx.java,XxxxMapper,XxxxMapper.xml,注释为英文-->
<!--<groupId>org.mybatis.generator</groupId>-->
<!--<artifactId>mybatis-generator-maven-plugin</artifactId>-->
<!--<version>1.3.6</version>-->
<!--<dependencies>-->
<!--<!–mysql数据库驱动–>-->
<!--<dependency>-->
<!--<groupId>mysql</groupId>-->
<!--<artifactId>mysql-connector-java</artifactId>-->
<!--<version>${mysql.version}</version>-->
<!--</dependency>-->
<!--</dependencies>-->
<!--MyBatis-generator + li24361/mybatis-generator-core插件-->
<!--生成结果:XxxxEntity.java,XxxxDao.java,XxxxDao.xml,注释为中文(XxxxEntity字段、方法中文注释,XxxxDao方法中文注释)-->
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<dependencies>
<!--mysql数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.haier.hairy</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
<configuration>
<!--MyBatis-generator配置文件的位置-->
<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
<!--是否覆盖同名文件,默认为false-->
<overwrite>true</overwrite>
<!--是否将执行过程输出到控制台-->
<verbose>true</verbose>
</configuration>
</plugin>


3.4.修改generatorConfig.xml

<!--注释生成配置-->
<!--原始版本:注释为英文,生成结果:Xxxx.java,XxxxMapper,XxxxMapper.xml,-->
<!--<commentGenerator>-->
<!--扩展版本:中文注释,生成结果:XxxxEntity.java,XxxxDao.java,XxxxDao.xml -->
<commentGenerator type="org.mybatis.generator.internal.HairyCommentGenerator">
<property name="javaFileEncoding" value="UTF-8"/>
<!--是否抑制所有的注释,默认为false-->
<property name="suppressAllComments" value="false"/>
<!--是否抑制注释中的时间,默认为false,这里改为true,不生成时间(如果生成时间,则每次都是新版本,每次都要提交)-->
<property name="suppressDate" value="true"/>
</commentGenerator>


3.5.运行MyBatis Generator

3.6.生成结果

生成目录如下:

src
\---main
\---java
|   \---pers
|       \---hanchao
|           \---himybatis
|               \---generator
|                   \---dao
|                   |   \---TopicDao.java
|                   |---entity
|                       \---TopicEntity.java
\---webapp
\---generator
\---TopicDao.xml


代码展示:

TopicEntity.java

只详细展示第一个字段,后续字段和方法略。

package pers.hanchao.himybatis.generator.entity;

public class TopicEntity {
/**
* <pre>
* 话题
* 表字段 : topic.id
* </pre>
*/
private Integer id;

//other fields

//setter getter toString hashCode equals
}


TopicDao.java

只详细展示第一个方法,后续方法略。

package pers.hanchao.himybatis.generator.dao;

import java.util.List;
import pers.hanchao.himybatis.generator.entity.TopicEntity;

public interface TopicDao {
/**
* 根据主键删除数据库的记录
*
* @param id
*/
int deleteByPrimaryKey(Integer id);

//int insert(Topic record);
//Topic selectByPrimaryKey(Integer id);
//List<Topic> selectAll();
//int updateByPrimaryKey(Topic record);
}


TopicDao.xml的内容和之前一样,不再赘述。

总结:通过使用由
li24361
提供的https://github.com/li24361/mybatis-generator-core,确实达到了之前的目的:

生成可用的中文注释

更符合开发习惯的命名规范:TopicEntity.java、TopicDao.java、TopicDao.xml

4.测试生成代码的可用性

通过简单的
TopicApp.java
完成对生成的TopicEntity.java、TopicDao.java、TopicDao.xml可用性测试。

TopicApp.java

package pers.hanchao.himybatis.generator;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.log4j.Logger;
import pers.hanchao.himybatis.generator.dao.TopicDao;
import pers.hanchao.himybatis.generator.entity.TopicEntity;

import java.io.IOException;
import java.io.Reader;

/**
* <p>测试MyBatis Generator生成的代码是否可用</p>
* @author hanchao 2018/2/4 10:45
**/
public class TopicApp {
/** 日志 */
private static final Logger LOGGER = Logger.getLogger(TopicApp.class);

/** 配置文件读取类 */
private static Reader reader;

/** 会话工厂 */
private static SqlSessionFactory sqlSessionFactory;

static {
try {
//读取配置文件
reader = Resources.getResourceAsReader("mybatis-config-generator.xml");
//构建会话工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* <p>对MyBatis Generator生成的数据库方法进行测试</p>
* @author hanchao 2018/2/4 10:46
**/
public static void main(String[] args) {
//创建会话
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
//获取Dao层实例
TopicDao topicDao = sqlSession.getMapper(TopicDao.class);
//查询所有
LOGGER.info("查询所有");
LOGGER.info(topicDao.selectAll());
//插入一个,查询所有
System.out.println();
LOGGER.info("插入一个");
TopicEntity newTopic = new TopicEntity();
newTopic.setId(100);
newTopic.setTitle("新增的标题");
newTopic.setScore(200);
newTopic.setAnswer("新增的答案");
topicDao.insert(newTopic);
LOGGER.info(topicDao.selectAll());
//查询一个
System.out.println();
LOGGER.info("查询一个");
LOGGER.info(topicDao.selectByPrimaryKey(1));
//修改一个,然后查询
System.out.println();
LOGGER.info("修改一个");
newTopic = new TopicEntity();
newTopic.setId(1);
newTopic.setTitle("修改的标题");
newTopic.setScore(1000);
newTopic.setAnswer("修改的答案");
topicDao.updateByPrimaryKey(newTopic);
LOGGER.info(topicDao.selectByPrimaryKey(1));
//删除一个,然后查询
System.out.println();
LOGGER.info("删除一个,然后查询");
topicDao.deleteByPrimaryKey(1);
LOGGER.info(topicDao.selectByPrimaryKey(1));

//提交
sqlSession.commit();
}catch (Exception e){
e.printStackTrace();
LOGGER.info("error!");
sqlSession.rollback();
}finally {
sqlSession.close();
}
}
}


运行结果:

2018-02-04 16:38:59 INFO  TopicApp:49 - 查询所有
2018-02-04 16:38:59 DEBUG JdbcTransaction:54 - Opening JDBC Connection
2018-02-04 16:39:00 DEBUG PooledDataSource:54 - Created connection 1316864772.
2018-02-04 16:39:00 DEBUG JdbcTransaction:54 - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4e7dc304]
2018-02-04 16:39:00 DEBUG selectAll:54 - ==>  Preparing: select id, title, score, answer from topic
2018-02-04 16:39:00 DEBUG selectAll:54 - ==> Parameters:
2018-02-04 16:39:00 DEBUG selectAll:54 - <==      Total: 2
2018-02-04 16:39:00 INFO  TopicApp:50 - [TopicEntity [Hash = -756562783, id=1, title=新话题1111, score=1001111, answer=新答案111], TopicEntity [Hash = 1936880702, id=99999, title=题目1, score=100, answer=你好吗?]]

2018-02-04 16:39:00 INFO  TopicApp:53 - 插入一个
2018-02-04 16:39:00 DEBUG insert!selectKey:54 - ==>  Preparing: SELECT LAST_INSERT_ID()
2018-02-04 16:39:00 DEBUG insert!selectKey:54 - ==> Parameters:
2018-02-04 16:39:00 DEBUG insert!selectKey:54 - <==      Total: 1
2018-02-04 16:39:00 DEBUG insert:54 - ==>  Preparing: insert into topic (id, title, score, answer) values (?, ?, ?, ?)
2018-02-04 16:39:00 DEBUG insert:54 - ==> Parameters: 0(Integer), 新增的标题(String), 200(Integer), 新增的答案(String)
2018-02-04 16:39:00 DEBUG insert:54 - <==    Updates: 1
2018-02-04 16:39:00 DEBUG selectAll:54 - ==>  Preparing: select id, title, score, answer from topic
2018-02-04 16:39:00 DEBUG selectAll:54 - ==> Parameters:
2018-02-04 16:39:00 DEBUG selectAll:54 - <==      Total: 3
2018-02-04 16:39:00 INFO  TopicApp:60 - [TopicEntity [Hash = -756562783, id=1, title=新话题1111, score=1001111, answer=新答案111], TopicEntity [Hash = 1936880702, id=99999, title=题目1, score=100, answer=你好吗?], TopicEntity [Hash = -1744254903, id=100001, title=新增的标题, score=200, answer=新增的答案]]

2018-02-04 16:39:00 INFO  TopicApp:63 - 查询一个
2018-02-04 16:39:00 DEBUG selectByPrimaryKey:54 - ==>  Preparing: select id, title, score, answer from topic where id = ?
2018-02-04 16:39:00 DEBUG selectByPrimaryKey:54 - ==> Parameters: 1(Integer)
2018-02-04 16:39:00 DEBUG selectByPrimaryKey:54 - <==      Total: 1
2018-02-04 16:39:00 INFO  TopicApp:64 - TopicEntity [Hash = -756562783, id=1, title=新话题1111, score=1001111, answer=新答案111]

2018-02-04 16:39:00 INFO  TopicApp:67 - 修改一个
2018-02-04 16:39:00 DEBUG updateByPrimaryKey:54 - ==>  Preparing: update topic set title = ?, score = ?, answer = ? where id = ?
2018-02-04 16:39:00 DEBUG updateByPrimaryKey:54 - ==> Parameters: 修改的标题(String), 1000(Integer), 修改的答案(String), 1(Integer)
2018-02-04 16:39:00 DEBUG updateByPrimaryKey:54 - <==    Updates: 1
2018-02-04 16:39:00 DEBUG selectByPrimaryKey:54 - ==>  Preparing: select id, title, score, answer from topic where id = ?
2018-02-04 16:39:00 DEBUG selectByPrimaryKey:54 - ==> Parameters: 1(Integer)
2018-02-04 16:39:00 DEBUG selectByPrimaryKey:54 - <==      Total: 1
2018-02-04 16:39:00 INFO  TopicApp:74 - TopicEntity [Hash = 1122539663, id=1, title=修改的标题, score=1000, answer=修改的答案]

2018-02-04 16:39:00 INFO  TopicApp:77 - 删除一个,然后查询
2018-02-04 16:39:00 DEBUG deleteByPrimaryKey:54 - ==>  Preparing: delete from topic where id = ?
2018-02-04 16:39:00 DEBUG deleteByPrimaryKey:54 - ==> Parameters: 1(Integer)
2018-02-04 16:39:00 DEBUG deleteByPrimaryKey:54 - <==    Updates: 1
2018-02-04 16:39:00 DEBUG selectByPrimaryKey:54 - ==>  Preparing: select id, title, score, answer from topic where id = ?
2018-02-04 16:39:00 DEBUG selectByPrimaryKey:54 - ==> Parameters: 1(Integer)
2018-02-04 16:39:00 DEBUG selectByPrimaryKey:54 - <==      Total: 0
2018-02-04 16:39:00 INFO  TopicApp:79 -


5.参考资料与更多扩展

参考资料:

官方半中文网

MyBatis学习之代码生成器Generator

https://github.com/li24361/mybatis-generator-core

mybatis-generator代码生成解决生成数据库的注释

MyBatis Generator 详解

更多扩展:

mybatis-generator-gui:基于mybatis generator开发一款界面工具

MyBatis Generator 插件的拓展插件包:MySQL分页插件、查询单条数据插件等等
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐