一、什么是逆向工程
Mybatis的逆向工程就是由代码生成器生成我们需要的代码和映射文件。我们在编写Mybatis程序时,基本都是围绕着pojo类,Mapper接口,Mapper.xml文件等文件来进行的。如果实际开发中数据库的表特别多,那么我们需要手动去写每一张表的pojo类,Mapper接口,Mapper.xml文件,这显然需要花费巨大的精力,而且可能由于表字段太多,哪里写错了都难以排除。所以我们在实际开发中,一般使用逆向工程方式来自动生成所需的文件,这也是企业中一种非常常见的方法。
注意:在使用逆向工程生成代码文件的时候,最好额外创建一个项目,不要在原来的项目中使用,因为如果你在原项目中有相同名字的文件,那么就会被新生成的文件所覆盖,导致之前写的代码没了,有一定的风险。所以实际开发中,我们一般新建一个项目,然后将生成的文件复制到自己的所需的工程中。

1、MGB简介
官方文档 : http://mybatis.org/generator/
逆向工程包的下载地址: https://github.com/mybatis/generator/releases/tag/mybatis-generator-1.3.2
(1)MyBatis Generator:即MBG
(2)MBG是一个专门为MyBatis框架使用者定制的代码生成器
(3)MBG可以快速的根据表生成对应的映射文件、接口、以及bean类
(4)只可以生成单表CRUD,但是表连接、存储过程等这些复杂sql的定义需要我们手工编写
2、编写MBG的配置文件mbg.xml(重要几处配置)
相应的配置文件在官方文档中,可以找到

向下滑动


上述配置文件是官方给出的示例配置文件,之后将其中相关部分改为和自己模块匹配的内容
3、运行程序(代码生成器)

二、逆向工程生成代码
①、首先创建maven项目
1、项目整体目录:

2、导入maven依赖:
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!-- 日志处理 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- 逆向工程 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
②、创建日志文件log4j.properties
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
③、创建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>
<!--targetRuntime="MyBatis3Simple"表示生成简易版本,这里创建原始版本,参数为MyBatis3-->
<context id="testTables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释。true:是;false:否 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8"
userId="root"
password="root">
</jdbcConnection>
<!-- 默认false,把JDBC DECIMAL和NUMERIC类型解析为Integer,为true时把JDBC DECIMAL 和
NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- targetProject:POJO类生成的位置 -->
<javaModelGenerator targetPackage="com.example.pojo"
targetProject="./src/main/java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="com.example.mapper"
targetProject="./src/main/resources">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.example.mapper"
targetProject="./src/main/java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!--生成全部表tableName设为%-->
<!-- 可选:-->
<!-- 1,schema:数据库的schema;-->
<!-- 2,catalog:数据库的catalog;-->
<!-- 3,alias:为数据表设置的别名,如果设置了alias,那么生成的所有的SELECT SQL语句中,列名会变成:alias_actualColumnName-->
<!-- 4,domainObjectName:生成的domain类的名字,如果不设置,直接使用表名作为domain类的名字;可以设置为somepck.domainName,那么会自动把domainName类再放到somepck包里面;-->
<!-- 5,enableInsert(默认true):指定是否生成insert语句;-->
<!-- 6,enableSelectByPrimaryKey(默认true):指定是否生成按照主键查询对象的语句(就是getById或get);-->
<!-- 7,enableSelectByExample(默认true):MyBatis3Simple为false,指定是否生成动态查询语句;-->
<!-- 8,enableUpdateByPrimaryKey(默认true):指定是否生成按照主键修改对象的语句(即update);-->
<!-- 9,enableDeleteByPrimaryKey(默认true):指定是否生成按照主键删除对象的语句(即delete);-->
<!-- 10,enableDeleteByExample(默认true):MyBatis3Simple为false,指定是否生成动态删除语句;-->
<!-- 11,enableCountByExample(默认true):MyBatis3Simple为false,指定是否生成动态查询总条数语句(用于分页的总条数查询);-->
<!-- 12,enableUpdateByExample(默认true):MyBatis3Simple为false,指定是否生成动态修改语句(只修改对象中不为空的属性);-->
<!-- 13,modelType:参考context元素的defaultModelType,相当于覆盖;-->
<!-- 14,delimitIdentifiers:参考tableName的解释,注意,默认的delimitIdentifiers是双引号,如果类似MYSQL这样的数据库,使用的是`(反引号,那么还需要设置context的beginningDelimiter和endingDelimiter属性)-->
<!-- 15,delimitAllColumns:设置是否所有生成的SQL中的列名都使用标识符引起来。默认为false,delimitIdentifiers参考context的属性-->
<!-- 指定生成哪些数据库表,要和数据库中对应,不能写错了,这里以t_user表为例,可以写多个;domainObjectName是要生成的实体类名称-->
<!-- 指定数据库表 [SQLServer] schema=""必须为空 -->
<table schema="mybatis" tableName="t_user"/>
<!-- 有些表的字段需要指定java类型 -->
<!-- <table schema="" tableName="">
<columnOverride column="" javaType="" />
</table> -->
</context>
</generatorConfiguration>
注意:serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8中的 & 要改成转义字符 & 这里传上来页面自动给转成了 &。

还有就是不同的数据库中不能含有相同的表,例如数据库A有t_user表,数据库B也有t_user表,那么到时候代码不知道生成哪个,而我恰好生成的是我们不需要的那个。啊?你说上面不是指定了数据库吗,怎么会到读取到其它数据库的表,不好意思,我试了不下十遍,最后我把其它数据库同名的表删除才成功的。如果你没有这种情况那更好咯。
④、创建逆向工程核心生成代码GeneratorSql.java
package com.thr.generator;
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.File;
import java.util.ArrayList;
import java.util.List;
/**
* 逆向工程核心生成代码
*/
public class GeneratorSql {
public void generator() throws Exception {
List<String> warnings = new ArrayList<>();
boolean overwrite = true;
// 指定逆向工程配置文件
String file = GeneratorSql.class.getResource("/generatorConfig.xml").getFile();
File configFile = new File(file);
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
}
// 执行main方法以生成代码
public static void main(String[] args) {
try {
GeneratorSql generatorSql = new GeneratorSql();
generatorSql.generator();
} catch (Exception e) {
e.printStackTrace();
}
}
}
⑤、运行逆向工程核心生成代码
运行上面的程序,如果控制台打印了如下日志,说明生成代码成功了。

然后我们再看项目就会发现生成了如下文件:

三、逆向工程举例
首先我们将上面生成的文件复制到目标项目中。在使用逆向工程举例之前,先来介绍生成的文件有哪些东西:
(1)、TUserMapper接口生成的方法介绍:


- long countByExample(TUserExample example):按条件计数
- int deleteByExample(TUserExample example):按条件删除
- int deleteByPrimaryKey(Integer id):按主键删除
- int insert(TUser record):插入数据(返回值为ID)
- int insertSelective(TUser record):插入数据,只插入值不为null的字段,内部动态sql判断
- List selectByExample(TUserExample example):按条件查询,传入null表示查询所有
- TUser selectByPrimaryKey(Integer id):按主键查询
- int updateByExampleSelective(@Param(“record”) TUser record, @Param(“example”) TUserExample example):按条件更新值不为null的字段
- int updateByExample(@Param(“record”) TUser record, @Param(“example”) TUserExample example):按条件更新
- int updateByPrimaryKeySelective(TUser record):按主键更新值不为null的字段
- int updateByPrimaryKey(TUser record):按主键更新
测试不带条件的方法:
//Mybatis的测试
public class MybatisTest {
//定义 SqlSession
private SqlSession sqlSession = null;
//定义 TUserMapper对象
private TUserMapper mapper = null;
@Before//在测试方法执行之前执行
public void getSqlSession(){
//1、加载 mybatis 全局配置文件
InputStream is = MybatisTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
//2、创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3、根据 sqlSessionFactory 产生session
sqlSession = sqlSessionFactory.openSession();
//4、创建Mapper接口的的代理对象,getMapper方法底层会通过动态代理生成TUserMapper的代理实现类
mapper = sqlSession.getMapper(TUserMapper.class);
}
@After//在测试方法执行完成之后执行
public void destroy() throws IOException {
sqlSession.commit();
sqlSession.close();
}
//查询所有用户信息
@Test
public void selectAllUser(){
List<TUser> tUsers = mapper.selectByExample(null);//传入null表示查询所有
for (TUser tUser : tUsers) {
System.out.println(tUser);
}
}
//根据用户id查询用户
@Test
public void selectByUserId(){
TUser tUser = mapper.selectByPrimaryKey(1);
System.out.println(tUser);
}
//添加用户信息
@Test
public void insertUser(){
TUser tUser = new TUser();
tUser.setUsername("凡尔赛");
tUser.setAge(18);
tUser.setBirthday(new Date());
tUser.setSex("0");
tUser.setAddress("漂亮国");
int i = mapper.insertSelective(tUser);
System.out.println(i>0?"添加成功":"添加失败");
}
//更新用户信息
@Test
public void updateUser(){
TUser tUser = new TUser();
tUser.setId(8);//这里要设置id才能修改成功,否则不知道修改哪一条数据
tUser.setUsername("川建国");
tUser.setAge(50);
tUser.setBirthday(new Date());
tUser.setSex("1");
tUser.setAddress("漂亮国");
int i = mapper.updateByPrimaryKeySelective(tUser);
System.out.println(i>0?"修改成功":"修改失败");
}
//删除用户信息
@Test
public void deleteUser(){
int i = mapper.deleteByPrimaryKey(8);
System.out.println(i>0?"删除成功":"删除失败");
}
}
(2)、TUserExample条件扩展类介绍:
上面的测试方法是不带条件的操作,那么接下来学习一下按条件如何进行增删改查操作,我们在逆向工程中已经生成了这个类TUserExample,这个类就是一个条件扩展类,里面定义了一系列方法用来做条件,比如:排序、去重、大于、小于、等于、模糊查询、数据在某某之间等等。
我们在TUserExample类中可以看到定义了一个内部类GeneratedCriteria,这个内部类就定义了一系列条件的方法,这些条件最后都会拼接在SQL中,但是我们一般不用它,都用它的子类Criteria来进行操作,Criteria继承了内部类GeneratedCriteria。

简单举例:
//Mybatis的测试
public class MybatisTest1 {
//定义 SqlSession
private SqlSession sqlSession = null;
//定义 UserMapper对象
private TUserMapper mapper = null;
@Before//在测试方法执行之前执行
public void getSqlSession(){
//1、加载 mybatis 全局配置文件
InputStream is = MybatisTest1.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
//2、创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3、根据 sqlSessionFactory 产生session
sqlSession = sqlSessionFactory.openSession();
//4、创建Mapper接口的的代理对象,getMapper方法底层会通过动态代理生成UserMapper的代理实现类
mapper = sqlSession.getMapper(TUserMapper.class);
}
@After//在测试方法执行完成之后执行
public void destroy() throws IOException {
sqlSession.commit();
sqlSession.close();
}
//模糊查询用户信息
@Test
public void selectUserLike(){
TUserExample example = new TUserExample();
TUserExample.Criteria criteria = example.createCriteria();
//模糊条件
criteria.andUsernameLike("%三%");
/*sql语句相当于:select id, username, age, birthday, sex, address
from t_user WHERE ( username like ? )*/
List<TUser> tUsers = mapper.selectByExample(example);
for (TUser tUser : tUsers) {
System.out.println(tUser);
}
}
//查询年龄在18-30岁之间的用户信息
@Test
public void selectUserBetween(){
TUserExample example = new TUserExample();
TUserExample.Criteria criteria = example.createCriteria();
//Between条件
criteria.andAgeBetween(18,30);
example.or(criteria);
example.setDistinct(true);
/*sql语句相当于:select distinct id, username, age, birthday, sex, address
from t_user WHERE ( age between ? and ? ) or( age between ? and ? )*/
List<TUser> tUsers = mapper.selectByExample(example);
for (TUser tUser : tUsers) {
System.out.println(tUser);
}
}
//查询用户名A或B
@Test
public void selectUserOr(){
TUserExample example = new TUserExample();
TUserExample.Criteria criteria1 = example.createCriteria();
criteria1.andUsernameEqualTo("黄飞鸿");
TUserExample.Criteria criteria2 = example.createCriteria();
criteria2.andUsernameEqualTo("马保国");
//将criteria2条件拼接在 or 关键字字后面
example.or(criteria2);
/*sql语句相当于:select id, username, age, birthday, sex, address
from t_user WHERE ( username = ? ) or( username = ? )*/
List<TUser> tUsers = mapper.selectByExample(example);
for (TUser tUser : tUsers) {
System.out.println(tUser);
}
}
//根据用户名删除用户
@Test
public void deleteUserExample(){
TUserExample example = new TUserExample();
TUserExample.Criteria criteria = example.createCriteria();
criteria.andUsernameEqualTo("凡尔赛");
//sql语句相当于:delete from t_user WHERE ( username = ? )
int i = mapper.deleteByExample(example);
System.out.println(i>0?"删除成功":"删除失败");
}
}
至此Mybatis的逆向工程就全部介绍完成了,说难也不是特别难,只要一步步自己去实现,去理解一遍,是非常简单的,可能复杂一点的是那个XxxExample类,但如果自己多举几个例子也不难。
四、逆向工程代码扩展
问:MyBatis Generator 为什么不生成 service 层和 controller 层 ?
答:mybatis 是持久层框架。
①、自定义注释生成器
1、创建自定义注释生成器 CommentGenerator.java
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;
/**
* 自定义注释生成器
* Created by macro on 2018/4/26.
*/
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));
}
}
}
2、添加 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="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.jzxs.etp.mbg.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>
<!--指定生成model的路径-->
<javaModelGenerator targetPackage="com.jzxs.etp.mbg.model"
targetProject="./src/main/java"/>
<!--指定生成mapper.xml的路径-->
<sqlMapGenerator targetPackage="com.jzxs.etp.mbg.mapper"
targetProject="./src/main/resources"/>
<!--指定生成mapper接口的的路径-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.jzxs.etp.mbg.mapper"
targetProject="./src/main/java"/>
<!--生成全部表tableName设为%-->
<table tableName="history_picture"></table>
</context>
</generatorConfiguration>
②、自定义Controller和Service插件
1、自定义生成Controller和Service的模板。
package com.jzxs.etp.mbg;
import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import java.util.ArrayList;
import java.util.List;
import static org.mybatis.generator.internal.util.StringUtility.stringHasValue;
import static org.mybatis.generator.internal.util.messages.Messages.getString;
public class ServiceAndControllerGeneratorPlugin extends PluginAdapter {
// 项目目录,一般为 src/main/java
private String targetProject;
// service包名,如:com.thinkj2ee.cms.service.service
private String servicePackage;
// service实现类包名,如:com.thinkj2ee.cms.service.service.impl
private String serviceImplPackage;
// Controlle类包名,如:com.thinkj2ee.cms.service.controller
private String controllerPackage;
// service接口名前缀
private String servicePreffix;
// service接口名后缀
private String serviceSuffix;
// service接口的父接口
private String superServiceInterface;
// service实现类的父类
private String superServiceImpl;
// controller类的父类
private String superController;
// dao接口基类
private String superDaoInterface;
// Example类的包名
private String examplePacket;
private String recordType;
private String modelName;
private FullyQualifiedJavaType model;
private String serviceName;
private String serviceImplName;
private String controllerName;
@Override
public boolean validate(List<String> warnings) {
boolean valid = true;
/* if (!stringHasValue(properties
.getProperty("targetProject"))) { //$NON-NLS-1$
warnings.add(getString("ValidationError.18", //$NON-NLS-1$
"MapperConfigPlugin", //$NON-NLS-1$
"targetProject")); //$NON-NLS-1$
valid = false;
}
if (!stringHasValue(properties.getProperty("servicePackage"))) { //$NON-NLS-1$
warnings.add(getString("ValidationError.18", //$NON-NLS-1$
"MapperConfigPlugin", //$NON-NLS-1$
"servicePackage")); //$NON-NLS-1$
valid = false;
}
if (!stringHasValue(properties.getProperty("serviceImplPackage"))) { //$NON-NLS-1$
warnings.add(getString("ValidationError.18", //$NON-NLS-1$
"MapperConfigPlugin", //$NON-NLS-1$
"serviceImplPackage")); //$NON-NLS-1$
valid = false;
}
*/
targetProject = properties.getProperty("targetProject");
servicePackage = properties.getProperty("servicePackage");
serviceImplPackage = properties.getProperty("serviceImplPackage");
servicePreffix = properties.getProperty("servicePreffix");
servicePreffix = stringHasValue(servicePreffix) ? servicePreffix : "";
serviceSuffix = properties.getProperty("serviceSuffix");
serviceSuffix = stringHasValue(serviceSuffix) ? serviceSuffix : "";
superServiceInterface = properties.getProperty("superServiceInterface");
superServiceImpl = properties.getProperty("superServiceImpl");
superDaoInterface = properties.getProperty("superDaoInterface");
controllerPackage = properties.getProperty("controllerPackage");
superController = properties.getProperty("superController");
return valid;
}
@Override
public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
recordType = introspectedTable.getBaseRecordType();
modelName = recordType.substring(recordType.lastIndexOf(".") + 1);
model = new FullyQualifiedJavaType(recordType);
serviceName = servicePackage + "." + servicePreffix + modelName + serviceSuffix;
serviceImplName = serviceImplPackage + "." + modelName + serviceSuffix+"Impl";
examplePacket=recordType.substring(0,recordType.lastIndexOf("."));
controllerName=controllerPackage.concat(".").concat(modelName).concat("Controller");
List<GeneratedJavaFile> answer = new ArrayList<>();
GeneratedJavaFile gjf = generateServiceInterface(introspectedTable);
GeneratedJavaFile gjf2 = generateServiceImpl(introspectedTable);
GeneratedJavaFile gjf3 = generateController(introspectedTable);
answer.add(gjf);
answer.add(gjf2);
answer.add(gjf3);
return answer;
}
// 生成service接口
private GeneratedJavaFile generateServiceInterface(IntrospectedTable introspectedTable) {
FullyQualifiedJavaType service = new FullyQualifiedJavaType(serviceName);
Interface serviceInterface = new Interface(service);
serviceInterface.setVisibility(JavaVisibility.PUBLIC);
// 添加父接口
if(stringHasValue(superServiceInterface)) {
String superServiceInterfaceName = superServiceInterface.substring(superServiceInterface.lastIndexOf(".") + 1);
serviceInterface.addImportedType(new FullyQualifiedJavaType(superServiceInterface));
serviceInterface.addImportedType(new FullyQualifiedJavaType(recordType));
serviceInterface.addSuperInterface(new FullyQualifiedJavaType(superServiceInterfaceName + "<" + modelName + ">"));
}
GeneratedJavaFile gjf = new GeneratedJavaFile(serviceInterface, targetProject, context.getJavaFormatter());
return gjf;
}
// 生成serviceImpl实现类
private GeneratedJavaFile generateServiceImpl(IntrospectedTable introspectedTable) {
FullyQualifiedJavaType service = new FullyQualifiedJavaType(serviceName);
FullyQualifiedJavaType serviceImpl = new FullyQualifiedJavaType(serviceImplName);
TopLevelClass clazz = new TopLevelClass(serviceImpl);
//描述类的作用域修饰符
clazz.setVisibility(JavaVisibility.PUBLIC);
//描述类 引入的类
clazz.addImportedType(service);
//描述类 的实现接口类
clazz.addSuperInterface(service);
if(stringHasValue(superServiceImpl)) {
String superServiceImplName = superServiceImpl.substring(superServiceImpl.lastIndexOf(".") + 1);
clazz.addImportedType(superServiceImpl);
clazz.addImportedType(recordType);
clazz.setSuperClass(superServiceImplName + "<" + modelName + ">");
}
clazz.addImportedType(new FullyQualifiedJavaType("org.springframework.stereotype.Service"));
clazz.addAnnotation("@Service");
String daoFieldType = introspectedTable.getMyBatis3JavaMapperType();
String daoFieldName = firstCharToLowCase(daoFieldType.substring(daoFieldType.lastIndexOf(".") + 1));
//描述类的成员属性
Field daoField = new Field(daoFieldName, new FullyQualifiedJavaType(daoFieldType));
clazz.addImportedType(new FullyQualifiedJavaType(daoFieldType));
clazz.addImportedType(new FullyQualifiedJavaType("org.springframework.beans.factory.annotation.Autowired"));
//描述成员属性 的注解
daoField.addAnnotation("@Autowired");
//描述成员属性修饰符
daoField.setVisibility(JavaVisibility.PRIVATE);
clazz.addField(daoField);
//描述 方法名
Method method = new Method("getMapper");
//方法注解
method.addAnnotation("@Override");
FullyQualifiedJavaType methodReturnType = new FullyQualifiedJavaType("Object");
//返回值
method.setReturnType(methodReturnType);
//方法体,逻辑代码
method.addBodyLine("return " + daoFieldName + ";");
//修饰符
method.setVisibility(JavaVisibility.PUBLIC);
clazz.addMethod(method);
Method method1 = new Method("getExample");
method1.addAnnotation("@Override");
FullyQualifiedJavaType methodReturnType1 = new FullyQualifiedJavaType("Object");
clazz.addImportedType(new FullyQualifiedJavaType(examplePacket.concat(".").concat(modelName).concat("Example")));
method1.setReturnType(methodReturnType1);
method1.addBodyLine("return new " + modelName + "Example();");
method1.setVisibility(JavaVisibility.PUBLIC);
clazz.addMethod(method1);
GeneratedJavaFile gjf2 = new GeneratedJavaFile(clazz, targetProject, context.getJavaFormatter());
return gjf2;
}
// 生成controller类
private GeneratedJavaFile generateController(IntrospectedTable introspectedTable) {
FullyQualifiedJavaType controller = new FullyQualifiedJavaType(controllerName);
TopLevelClass clazz = new TopLevelClass(controller);
//描述类的作用域修饰符
clazz.setVisibility(JavaVisibility.PUBLIC);
//添加@Controller注解,并引入相应的类
clazz.addImportedType(new FullyQualifiedJavaType("org.springframework.web.bind.annotation.RestController"));
clazz.addAnnotation("@RestController");
//添加@RequestMapping注解,并引入相应的类
clazz.addImportedType(new FullyQualifiedJavaType("org.springframework.web.bind.annotation.RequestMapping"));
clazz.addAnnotation("@RequestMapping(\"/"+firstCharToLowCase(modelName)+"\")");
//添加@Api注解,并引入相应的类
clazz.addImportedType(new FullyQualifiedJavaType("io.swagger.annotations.Api"));
String controllerSimpleName = controllerName.substring(controllerName.lastIndexOf(".")</


1411

被折叠的 条评论
为什么被折叠?



