generator逆向工程生成代码
首先引入jar包,数据库用mysql为例
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
配置文件
generator.properties, 都是一些数据库基本的连接配置,没什么可说的,一看就懂
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.connectionURL=jdbc:mysql://192.168.250.193:3306/micromall?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
jdbc.userId=root
jdbc.password=root
generatorConfig.xml,生成代码时的相关配置,如数据库连接配置、生成到哪个模块或package里面,以及需要执行哪些表,表的主键等信息说明
<?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="generator.properties"/>
<context id="MySqlContext" targetRuntime="MyBatis3" defaultModelType="flat">
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<property name="javaFileEncoding" value="UTF-8"/>
<!-- 为模型生成序列化方法-->
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<!-- 为生成的Java模型创建一个toString方法 -->
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
<!--生成mapper.xml时覆盖原文件-->
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin" />
<commentGenerator type="com.macro.mall.CommentGenerator">
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true"/>
<property name="suppressDate" value="true"/>
<property name="addRemarkComments" value="true"/>
</commentGenerator>
<jdbcConnection driverClass="${jdbc.driverClass}"
connectionURL="${jdbc.connectionURL}"
userId="${jdbc.userId}"
password="${jdbc.password}">
<!--解决mysql驱动升级到8.0后不生成指定数据库代码的问题-->
<property name="nullCatalogMeansCurrent" value="true" />
</jdbcConnection>
<javaModelGenerator targetPackage="com.macro.mall.model" targetProject="mall-mgb\src\main\java"/>
<sqlMapGenerator targetPackage="com.macro.mall.mapper" targetProject="mall-mgb\src\main\resources"/>
<javaClientGenerator type="XMLMAPPER" targetPackage="com.macro.mall.mapper"
targetProject="mall-mgb\src\main\java"/>
<!--生成全部表tableName设为%,指定前缀ums_%-->
<table tableName="wang_test" enableCountByExample="true" enableUpdateByExample="true"
enableDeleteByExample="true" enableSelectByExample="true"
selectByExampleQueryId="true">
<!-- generatedKey用于生成生成主键的方法,
如果设置了该元素,MBG会在生成的<insert>元素中生成一条正确的<selectKey>元素,该元素可选
column:主键的列名;
sqlStatement:要生成的selectKey语句,有以下可选项:
Cloudscape:相当于selectKey的SQL为: VALUES IDENTITY_VAL_LOCAL()
DB2 :相当于selectKey的SQL为: VALUES IDENTITY_VAL_LOCAL()
DB2_MF :相当于selectKey的SQL为:SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1
Derby :相当于selectKey的SQL为:VALUES IDENTITY_VAL_LOCAL()
HSQLDB :相当于selectKey的SQL为:CALL IDENTITY()
Informix :相当于selectKey的SQL为:select dbinfo('sqlca.sqlerrd1') from systables where tabid=1
MySql :相当于selectKey的SQL为:SELECT LAST_INSERT_ID()
SqlServer :相当于selectKey的SQL为:SELECT SCOPE_IDENTITY()
SYBASE :相当于selectKey的SQL为:SELECT @@IDENTITY
JDBC :相当于在生成的insert元素上添加useGeneratedKeys="true"和keyProperty属性
-->
<generatedKey column="id" sqlStatement="MySql" identity="true"/>
</table>
</context>
</generatorConfiguration>
自定义注释生成器
package com.macro.mall;
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.FullyQualifiedJavaType;
import org.mybatis.generator.internal.DefaultCommentGenerator;
import org.mybatis.generator.internal.util.StringUtility;
import java.util.Properties;
/**
* 自定义注释生成器
*/
public class CommentGenerator extends DefaultCommentGenerator {
private boolean addRemarkComments = false;
private static final String EXAMPLE_SUFFIX="Example";
private static final String API_MODEL_PROPERTY_FULL_CLASS_NAME="io.swagger.annotations.ApiModelProperty";
/**
* 设置用户配置的参数
*/
@Override
public void addConfigurationProperties(Properties properties) {
super.addConfigurationProperties(properties);
this.addRemarkComments = StringUtility.isTrue(properties.getProperty("addRemarkComments"));
}
/**
* 给字段添加注释
*/
@Override
public void addFieldComment(Field field, IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn) {
String remarks = introspectedColumn.getRemarks();
//根据参数和备注信息判断是否添加备注信息
if(addRemarkComments&&StringUtility.stringHasValue(remarks)){
// addFieldJavaDoc(field, remarks);
//数据库中特殊字符需要转义
if(remarks.contains("\"")){
remarks = remarks.replace("\"","'");
}
//给model的字段添加swagger注解
field.addJavaDocLine("@ApiModelProperty(value = \""+remarks+"\")");
}
}
/**
* 给model的字段添加注释
*/
private void addFieldJavaDoc(Field field, String remarks) {
//文档注释开始
field.addJavaDocLine("/**");
//获取数据库字段的备注信息
String[] remarkLines = remarks.split(System.getProperty("line.separator"));
for(String remarkLine:remarkLines){
field.addJavaDocLine(" * "+remarkLine);
}
addJavadocTag(field, false);
field.addJavaDocLine(" */");
}
@Override
public void addJavaFileComment(CompilationUnit compilationUnit) {
super.addJavaFileComment(compilationUnit);
//只在model中添加swagger注解类的导入
if(!compilationUnit.isJavaInterface()&&!compilationUnit.getType().getFullyQualifiedName().contains(EXAMPLE_SUFFIX)){
compilationUnit.addImportedType(new FullyQualifiedJavaType(API_MODEL_PROPERTY_FULL_CLASS_NAME));
}
}
}
执行生成代码的主类
package com.macro.mall;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* 用于生产MBG的代码
*/
public class Generator {
public static void main(String[] args) throws Exception {
//MBG 执行过程中的警告信息
List<String> warnings = new ArrayList<String>();
//当生成的代码重复时,覆盖原代码
boolean overwrite = true;
//读取我们的 MBG 配置文件
InputStream is = Generator.class.getResourceAsStream("/generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(is);
is.close();
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
//创建 MBG
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
//执行生成代码
myBatisGenerator.generate(null);
//输出警告信息
for (String warning : warnings) {
System.out.println(warning);
}
}
}
xxxEXample参数说明
参数的整体结构如下:
说明:
1、WangTestExample就是WangTest的参数类(WangTest是表wang_test的java实体类)。
该参数类中包含三个属性,一个是list集合,一个是排序字符串,一个是是否去重
List oredCriteria:这个里面在进行sql查询时使用的是OR 即 id = 1 or name = ‘jin’
2、Criteria:有两个属性,一个是所有的字段集合,一个是该批参数是否有效
下面用代码来说明图中表示的意思的具体实现:
注:因为这个参数类代码太多,只拿一个字段进行详细说明
package com.macro.mall.model;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class WangTestExample {
protected String orderByClause; // 排序字段 如 name asc
protected boolean distinct;// 是否去重
protected List<Criteria> oredCriteria;// 参数集合 该集合循环时用 or 表示并联查询
public WangTestExample() {
oredCriteria = new ArrayList<Criteria>();
}
//往 oredCriteria集合里面放入的Criteria 都是属于or查询,这种方法是先创建一个串联查询 criteria,然后再添加到集合中。即先创建赋值,再添加到集合中
public void or(Criteria criteria) {
oredCriteria.add(criteria);
}
// 先创建Criteria 添加到集合中,然后在进行参数赋值设置
public Criteria or() {
Criteria criteria = createCriteriaInternal();
oredCriteria.add(criteria);
return criteria;
}
//创建Criteria
public Criteria createCriteria() {
Criteria criteria = createCriteriaInternal();
if (oredCriteria.size() == 0) {
oredCriteria.add(criteria);
}
return criteria;
}
//创建Criteria
protected Criteria createCriteriaInternal() {
Criteria criteria = new Criteria();
return criteria;
}
//清除所有的参数
public void clear() {
oredCriteria.clear();
orderByClause = null;
distinct = false;
}
protected abstract static class GeneratedCriteria {
protected List<Criterion> criteria;//所有字段属性设置类集合
protected GeneratedCriteria() {
super();
criteria = new ArrayList<Criterion>();
}
//是否有效,表示该参数类是否生效
public boolean isValid() {
return criteria.size() > 0;
}
//设置条件的方法 condition 的值 如 name = 或 name is null
protected void addCriterion(String condition) {
if (condition == null) {
throw new RuntimeException("Value for condition cannot be null");
}
criteria.add(new Criterion(condition));
}
//设置条件和值的方法
//condition 同上
// value 值 如 jin
//property 属性名,如 name
protected void addCriterion(String condition, Object value, String property) {
if (value == null) {
throw new RuntimeException("Value for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value));
}
//设置两个值的方法
protected void addCriterion(String condition, Object value1, Object value2, String property) {
if (value1 == null || value2 == null) {
throw new RuntimeException("Between values for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value1, value2));
}
//添加参数 id 为null 的方法
public Criteria andIdIsNull() {
addCriterion("id is null");
return (Criteria) this;
}
// id 不为 null 的方法
public Criteria andIdIsNotNull() {
addCriterion("id is not null");
return (Criteria) this;
}
//id等于某个值的方法
public Criteria andIdEqualTo(Long value) {
addCriterion("id =", value, "id");
return (Criteria) this;
}
// 不等于
public Criteria andIdNotEqualTo(Long value) {
addCriterion("id <>", value, "id");
return (Criteria) this;
}
// id 大于 某个值
public Criteria andIdGreaterThan(Long value) {
addCriterion("id >", value, "id");
return (Criteria) this;
}
// id 大于等于 某个值
public Criteria andIdGreaterThanOrEqualTo(Long value) {
addCriterion("id >=", value, "id");
return (Criteria) this;
}
//id 小于 某个值
public Criteria andIdLessThan(Long value) {
addCriterion("id <", value, "id");
return (Criteria) this;
}
//id 小于等于 某个值
public Criteria andIdLessThanOrEqualTo(Long value) {
addCriterion("id <=", value, "id");
return (Criteria) this;
}
//id 在 某些值中
public Criteria andIdIn(List<Long> values) {
addCriterion("id in", values, "id");
return (Criteria) this;
}
//id 不在 某些值中
public Criteria andIdNotIn(List<Long> values) {
addCriterion("id not in", values, "id");
return (Criteria) this;
}
//id 在 某些值之间
public Criteria andIdBetween(Long value1, Long value2) {
addCriterion("id between", value1, value2, "id");
return (Criteria) this;
}
//id 不在 某些值中
public Criteria andIdNotBetween(Long value1, Long value2) {
addCriterion("id not between", value1, value2, "id");
return (Criteria) this;
}
//下面还有字段说明和id都是一样的用法,就不再一一累述,敲的累
//字符串有like ,模糊匹配 value值 为 %xxx%
public Criteria andNameLike(String value) {
addCriterion("name like", value, "name");
return (Criteria) this;
}
public Criteria andNameNotLike(String value) {
addCriterion("name not like", value, "name");
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {
protected Criteria() {
super();
}
}
//此类是某个字段的 属性说明
public static class Criterion {
private String condition;// 某字段的条件 如 name =
private Object value;//某字段的值 ,如果listValue为true则表示是个集合值
private Object secondValue;//某字段的第二个值 一般用于between
private boolean noValue;//是否无值
private boolean singleValue;// 是否一个值
private boolean betweenValue;//是否 between查询,用于二个值
private boolean listValue;//是否是list 值
private String typeHandler;//类型处理,暂时还未发现其用在何处
}
}
example的使用
都是自动生成的代码,下面只是简单的说明一下
int updateByExampleSelective(@Param("record") WangTest record, @Param("example") WangTestExample example);
List<WangTest> selectByExample(WangTestExample example);
为什么拿出来两个进行说明呢,主要是参数不一样,
@Param(“example”) WangTestExample example) 这种写法在,xml的sql中 与
List selectByExample(WangTestExample example);的用法有点小区别。下面看代码
<!--List<WangTest> selectByExample(WangTestExample example); 当一个参数的时候,默认是
_parameter ,所以在collection="oredCriteria" 时候省略了-->
<sql id="Example_Where_Clause">
首先先来个where
<where>
循环所有的参数集合,表示是并联查询,所以用or。criteria这里面表示的是一组串联参数集合
<foreach collection="oredCriteria" item="criteria" separator="or">
表示一组参数是否有效
<if test="criteria.valid">
如果参数有效,则进行串联查询 用and 连接
<trim prefix="(" prefixOverrides="and" suffix=")">
循环每个参数
<foreach collection="criteria.criteria" item="criterion">
<choose>
//如果该参数无值,则进行该步操作
<when test="criterion.noValue">
and ${criterion.condition}
</when>
//如果该参数有一个值,则进行该步操作
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
//如果between为true,则进行该步操作
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
//如果listValue为true,则进行该步操作
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<!-- int updateByExampleSelective(@Param("record") WangTest record, @Param("example") WangTestExample example);
下面这个查询条件的where与上面的一样,就example.oredCriteria不一样,主要是接口中有声明
@Param("example")
-->
<sql id="Update_By_Example_Where_Clause">
<where>
<foreach collection="example.oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>