1. 代码生成器原理分析
1.1
造句:
我们可以往空白内容进行填词造句,比如:
在比如:
再有:
1.2
观察我们之前写的代码,会发现其中也会有很多重复内容,比如:
那我们就想,如果我想做一个Book模块的开发,是不是只需要将红色部分的内容全部更换成Book
即可,如:
所以我们会发现,做任何模块的开发,对于这段代码,基本上都是对红色部分的调整,所以我们把去掉红色内容的东西称之为模板,红色部分称之为参数,以后只需要传入不同的参数,就可以根据模板创建出不同模块的dao代码。
除了Dao可以抽取模块,其实我们常见的类都可以进行抽取,只要他们有公共部分即可。再来看下模型类的模板:
- ① 可以根据数据库表的表名来填充
- ② 可以根据用户的配置来生成ID生成策略
- ③到⑨可以根据数据库表字段名称来填充
1.3
所以只要我们知道是对哪张表进行代码生成,这些内容我们都可以进行填充。
分析完后,我们会发现,要想完成代码自动生成,我们需要有以下内容:
- 模板: MyBatisPlus提供,
可以自己提供,但是麻烦,不建议 - 数据库相关配置:读取数据库获取表和字段信息
- 开发者自定义配置:手工配置,比如ID生成策略
2. 代码生成器实现
2.1 创建一个SpringBoot模块(子项目)
2.2 pom.xml中添加对应的依赖(导入对应的jar包)
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.7</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.yppah</groupId><artifactId>mp_04_generator</artifactId><version>0.0.1-SNAPSHOT</version><name>mp_04_generator</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><!--springboot--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!--spring webmvc--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--test--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><!--<scope>runtime</scope>--></dependency><!--druid--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.16</version></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--mybatisplus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.1</version></dependency><!--代码生成器--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.4.1</version></dependency><!--velocity模板引擎--><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.3</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
2.3 创建代码生成类
package com.yppah;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;public class Generator {public static void main(String[] args) {// 1. 创建代码生成器对象AutoGenerator autoGenerator = new AutoGenerator();// 2. 设置代码生成器//设置数据库相关配置DataSourceConfig dataSourceConfig = new DataSourceConfig();dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC");dataSourceConfig.setUsername("root");dataSourceConfig.setPassword("root");autoGenerator.setDataSource(dataSourceConfig);//设置全局配置GlobalConfig globalConfig = new GlobalConfig();globalConfig.setOutputDir(System.getProperty("user.dir")+"/mp_04_generator/src/main/java"); //设置代码生成位置globalConfig.setOpen(false); //设置生成完毕后是否打开生成代码所在的目录,默认trueglobalConfig.setAuthor("haifei"); //设置作者globalConfig.setFileOverride(true); //设置是否覆盖原始生成的文件,默认falseglobalConfig.setMapperName("%sDao"); //设置数据层接口名,%s为占位符,指代模块名称globalConfig.setIdType(IdType.ASSIGN_ID); //设置Id生成策略autoGenerator.setGlobalConfig(globalConfig);//设置包名相关配置PackageConfig packageInfo = new PackageConfig();packageInfo.setParent("com.yppah"); //设置生成的包名,与代码所在位置不冲突,二者叠加组成完整路径packageInfo.setEntity("domain"); //设置实体类包名packageInfo.setMapper("dao"); //设置数据层包名autoGenerator.setPackageInfo(packageInfo);//策略设置(核心)StrategyConfig strategyConfig = new StrategyConfig();strategyConfig.setInclude("tbl_user"); //设置当前参与生成的表名,参数为可变参数,如("tbl_user", "tbl_good", "tbl_order")strategyConfig.setTablePrefix("tbl_"); //设置数据库表的前缀名称,模块名 = 数据库表名 - 前缀名 例如: User = tbl_user - tbl_strategyConfig.setRestControllerStyle(true); //设置是否启用Rest风格strategyConfig.setVersionFieldName("version"); //设置乐观锁字段名strategyConfig.setLogicDeleteFieldName("deleted"); //设置逻辑删除字段名strategyConfig.setEntityLombokModel(true); //设置是否启用lombokautoGenerator.setStrategy(strategyConfig);// 3. 执行生成器autoGenerator.execute();}
}
对于代码生成器中的代码内容,我们可以直接从官方文档中获取代码进行修改,
https://mp.baomidou.com/guide/generator.html
2.4 测试:运行程序
运行成功后,会在当前项目中生成很多代码,代码包含controller
,service
,mapper
和entity
至此代码生成器就已经完成工作,能快速根据数据库表来创建对应的类,简化我们的代码开发。
package com.yppah.controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;/*** <p>* 前端控制器* </p>** @author haifei* @since 2022-05-17*/
@RestController
@RequestMapping("/user")
public class UserController {}
package com.yppah.dao;import com.yppah.domain.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;/*** <p>* Mapper 接口* </p>** @author haifei* @since 2022-05-17*/
public interface UserDao extends BaseMapper<User> {}
package com.yppah.domain;import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.Version;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;/*** <p>* * </p>** @author haifei* @since 2022-05-17*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("tbl_user")
public class User implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.AUTO)private Long id;private String name;private String pwd;private Integer age;private String tel;@TableLogicprivate Integer deleted;@Versionprivate Integer version;}
<?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="com.yppah.dao.UserDao"></mapper>
package com.yppah.service.impl;import com.yppah.domain.User;
import com.yppah.dao.UserDao;
import com.yppah.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;/*** <p>* 服务实现类* </p>** @author haifei* @since 2022-05-17*/
@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements IUserService {}
package com.yppah.service;import com.yppah.domain.User;
import com.baomidou.mybatisplus.extension.service.IService;/*** <p>* 服务类* </p>** @author haifei* @since 2022-05-17*/
public interface IUserService extends IService<User> {}
3. MP中Service的CRUD
MP代码生成器自动生成的Service层
回顾我们之前业务层代码的编写,编写接口和对应的实现类:
public interface UserService{}@Service
public class UserServiceImpl implements UserService{}
接口和实现类有了以后,需要在接口和实现类中声明方法
public interface UserService{public List<User> findAll();
}@Service
public class UserServiceImpl implements UserService{@Autowiredprivate UserDao userDao;public List<User> findAll(){return userDao.selectList(null);}
}
MP看到上面的代码以后就说这些方法也是比较固定和通用的,那我来帮你抽取下,所以MP提供了一个Service接口和实现类,分别是:IService
和ServiceImpl
,后者是对前者的一个具体实现。
以后我们自己写的Service就可以进行如下修改:
public interface UserService extends IService<User>{}@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService{}
修改以后的好处是,MP已经帮我们把业务层的一些基础的增删改查都已经实现了,可以直接进行使用。
编写测试类进行测试:
@SpringBootTest
class Mybatisplus04GeneratorApplicationTests {private IUserService userService;@Testvoid testFindAll() {List<User> list = userService.list();System.out.println(list);}}
注意:mp_04_generator项目中对于MyBatis的环境是没有进行配置,如果想要运行,需要提取将配置文件中的内容进行完善后在运行。
思考:在MP封装的Service层都有哪些方法可以用?
查看官方文档:https://mp.baomidou.com/guide/crud-interface.html
,这些提供的方法大家可以参考官方文档进行学习使用,方法的名称可能有些变化,但是方法对应的参数和返回值基本类似。