共计 13981 个字符,预计需要花费 35 分钟才能阅读完成。
Spring Boot 应用 Mybatis-plus 和它的代码生成器
这篇文章第一局部解说 Mybatis-plus 的应用。点上面的链接可返回官网。
但要留神的是。应用它仅是为了疾速开发,因为 sql 优化的第一点就是 sql 语句里的 select 不应间接写 * 也就是查找全副,而是应该写上每一个要用的字段。
第二局部写 Mybatis-plus 里的代码生成器,首先代码生成的代码实际上间接用 Mybatis-plus 官网里的范例就能够了,但要把生成的代码变成本人想要的样子,还是须要本人批改模板代码,所以这篇文章会展现出我当初应用的模板。
文章目录:
- Mybatis-Plus 应用
- 代码生成器
Mybatis-Plus 应用
pom.xml 中所需增加的依赖
// Mybatis-Plus 的包 | |
<dependency> | |
<groupId>com.baomidou</groupId> | |
<artifactId>mybatis-plus-boot-starter</artifactId> | |
<version>3.3.1.tmp</version> | |
</dependency> | |
// 代码结构器的包 | |
<dependency> | |
<groupId>com.baomidou</groupId> | |
<artifactId>mybatis-plus-generator</artifactId> | |
<version>3.3.1.tmp</version> | |
</dependency> | |
// 应用的页面模板是 freemarker | |
<dependency> | |
<groupId>org.freemarker</groupId> | |
<artifactId>freemarker</artifactId> | |
<version>2.3.30</version> | |
</dependency> | |
// lombok 的包,倡议下载插件,不下载插件代码会带红,但能够运行 | |
<dependency> | |
<groupId>org.projectlombok</groupId> | |
<artifactId>lombok</artifactId> | |
<optional>true</optional> | |
</dependency> | |
// 应用 pagehelper 来分页,Mybatis-plus 有分页的 Api,应用与否看本人 | |
<dependency> | |
<groupId>com.github.pagehelper</groupId> | |
<artifactId>pagehelper-spring-boot-starter</artifactId> | |
<version>1.2.10</version> | |
</dependency> | |
// 如果打算应用 swagger 增加上面两个注解 | |
<dependency> | |
<groupId>io.springfox</groupId> | |
<artifactId>springfox-swagger2</artifactId> | |
<version>2.9.2</version> | |
</dependency> | |
<dependency> | |
<groupId>io.springfox</groupId> | |
<artifactId>springfox-swagger-ui</artifactId> | |
<version>2.9.2</version> | |
</dependency> |
上面是我的项目构造和代码 其中 exception,config,until 不是波及这篇教程
Application.java
@EnableCaching | |
// 扫描 mapper 文件夹 | |
@MapperScan("com.generator.mapper") | |
@SpringBootApplication | |
public class GeneratorApplication {public static void main(String[] args) {SpringApplication.run(GeneratorApplication.class, args); | |
} | |
} |
实体类 entity
@Data | |
// 这个如果是 true 的话在 equal 时要思考其父类,因为这个类是没父类的所以为 false | |
// 我倡议这个中央大家去理解以下,和 equals() 这个办法无关,波及到父类与子类的.equals() | |
@EqualsAndHashCode(callSuper = false) | |
@Accessors(chain = true) | |
// 上面这个注解是 swagger 的 | |
@ApiModel(value="UserInfo 对象", description="") | |
public class UserInfo implements Serializable { | |
private static final long serialVersionUID = 1L; | |
// 上面这个是 Mybatis-Plus 的注解,主键申明,主动增长 | |
@TableId(value = "user_id", type = IdType.AUTO) | |
private Integer userId; | |
private String pwd; | |
private String userName; | |
private String userRealName; | |
private String telephone; | |
// swagger 注解 | |
@ApiModelProperty(value = "用户职业") | |
private String userPro; | |
} |
service 包下的
// 此处须要继承 IService<Entity>,来取得 Mybatis-plus 里的办法。// 这里其实是能够不必写上面这些,因为 Mybatis-plus 外部就有相应的 select 这些办法,相干请本人看官网文档 | |
// 但我还是倡议用本人设计的办法,可调用性更高 | |
public interface IUserInfoService extends IService<UserInfo> { | |
/** | |
* 查找 userInfo | |
* @param userInfo | |
* @param pageStart | |
* @param pageSize | |
* @return | |
*/ | |
List<UserInfo> findUserInfo(UserInfo userInfo, Integer pageStart, Integer pageSize); | |
/** | |
* 增加 userInfo | |
* @param userInfo | |
* @return | |
*/ | |
int insertUserInfo(UserInfo userInfo); | |
/** | |
* 批改 userInfo | |
* @param userInfo | |
* @return | |
*/ | |
int updateUserInfo(UserInfo userInfo); | |
/** | |
* 删除 userInfo | |
* @param id | |
* @return | |
*/ | |
int deleteUserInfo(int id); | |
} |
service 包里的 impl 文件夹下
// 申明是一个 Service 服务类,继承 ServiceImpl<Entity> 应用 Mybatis-plus 里的办法 | |
// 实现 IUserInfoService 里申明的接口 | |
@Service | |
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements IUserInfoService { | |
@Autowired | |
private UserInfoMapper userInfoMapper; | |
@Override | |
public List<UserInfo> findUserInfo(UserInfo userInfo, Integer pageStart, Integer pageSize) { | |
/* | |
这个是调用 QueryWrapper 里的 eq 这类的办法来本人构建一个 sql 语句 | |
QueryWrapper<UserInfo> queryWrapper=new QueryWrapper<>(); | |
queryWrapper.eq("userName",userInfo.getUserName()); | |
*/ | |
// 应用 QueryWrapper 条件结构器,此处是将对象间接存入,还有别的应用办法,外面间接依据状况调用 eq 这些 api 命令 | |
QueryWrapper<UserInfo> queryWrapper=new QueryWrapper<>(userInfo); | |
// 应用 pagehelper 来分页 | |
PageHelper.startPage(pageStart,pageSize); | |
// 调用 ServiceImpl 里的 selectList 办法 | |
return userInfoMapper.selectList(queryWrapper); | |
} | |
@Override | |
public int insertUserInfo(UserInfo userInfo) {return userInfoMapper.insert(userInfo); | |
} | |
@Override | |
public int updateUserInfo(UserInfo userInfo) {return userInfoMapper.updateById(userInfo); | |
} | |
@Override | |
public int deleteUserInfo(int id) {return userInfoMapper.deleteById(id); | |
} | |
} |
mapper 文件夹下
// 申明是一个接口, 继承 BaseMapper<Entity> | |
@Repository | |
public interface UserInfoMapper extends BaseMapper<UserInfo> {// 此处加自定义的 mapper} |
resources 下的 mapper 文件夹
<?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.generator.mapper.UserInfoMapper"> | |
</mapper> |
controller 文件夹下
// swagger 注解 | |
@Api(tags = "UserInfoController", description = "用户治理") | |
@RestController | |
@RequestMapping("/user-info") | |
public class UserInfoController { | |
// 这里我是以接口来申明一个变量,可间接应用 service 来申明 | |
@Autowired | |
private IUserInfoService userInfoService; | |
// swagger 注解 | |
@ApiOperation("查问用户") | |
@RequestMapping(value = "/list", method = RequestMethod.GET) | |
public RespBody findUserInfo(UserInfo userInfo, | |
@RequestParam(value = "pageStart",defaultValue = "1")Integer pageStart, | |
@RequestParam(value = "pageSize", defaultValue = "10")Integer pageSize){List<UserInfo> userInfoList = userInfoService.findUserInfo(userInfo, pageStart, pageSize); | |
// pagehelper 的返回类 | |
PageInfo<UserInfo> pageInfo = new PageInfo<>(userInfoList); | |
return RespBody.ok(pageInfo); | |
} | |
@ApiOperation("增加用户") | |
@RequestMapping(value = "/insert", method = RequestMethod.POST) | |
public RespBody insertUserInfo(UserInfo userInfo) {int result = userInfoService.insertUserInfo(userInfo); | |
if (result == 1) {return RespBody.ok(); | |
} | |
return RespBody.error();} | |
@ApiOperation("批改用户") | |
@RequestMapping(value = "/update", method = RequestMethod.POST) | |
public RespBody updateUserInfo(UserInfo userInfo) {int result = userInfoService.updateUserInfo(userInfo); | |
if (result == 1) {return RespBody.ok(); | |
} | |
return RespBody.error();} | |
@ApiOperation("删除用户") | |
@RequestMapping(value = "/delete", method = RequestMethod.POST) | |
public RespBody updateUserInfo(@RequestParam("id")int id) {int result = userInfoService.deleteUserInfo(id); | |
if (result == 1) {return RespBody.ok(); | |
} | |
return RespBody.error();} | |
} |
到此,下面就是应用我设计模板生成的相应代码了
我的 Mybatis-plus 代码生成器
代码
// 做出了一些批改,但总体上与官网里的代码雷同 | |
public class CodeGenerator { | |
/** | |
* <p> | |
* 读取控制台内容 | |
* </p> | |
*/ | |
public static String scanner(String tip) {Scanner scanner = new Scanner(System.in); | |
StringBuilder help = new StringBuilder(); | |
// 输出模块名 | |
help.append("请输出" + tip + ":"); | |
System.out.println(help.toString()); | |
if (scanner.hasNext()) {String ipt = scanner.next(); | |
if (StringUtils.isNotBlank(ipt)) {return ipt;} | |
} | |
throw new MybatisPlusException("请输出正确的" + tip + "!"); | |
} | |
public static void main(String[] args) { | |
// 代码生成器 | |
AutoGenerator mpg = new AutoGenerator(); | |
// 全局配置 | |
GlobalConfig gc = new GlobalConfig(); | |
String projectPath = System.getProperty("user.dir"); | |
// 输入的门路 | |
gc.setOutputDir(projectPath + "/src/main/java"); | |
// 作者 | |
gc.setAuthor("dell"); | |
gc.setOpen(false); | |
// 是否应用实体属性 Swagger2 注解 | |
gc.setSwagger2(true); | |
mpg.setGlobalConfig(gc); | |
// mysql 数据源配置 | |
DataSourceConfig dsc = new DataSourceConfig(); | |
dsc.setUrl("jdbc:mysql://localhost:3306/mall?serverTimezone=GMT%2B8&characterEncoding=UTF-8"); | |
dsc.setDriverName("com.mysql.cj.jdbc.Driver"); | |
dsc.setUsername("root"); | |
dsc.setPassword("*****"); | |
mpg.setDataSource(dsc); | |
// 包配置 | |
PackageConfig pc = new PackageConfig(); | |
// pc.setModuleName(scanner("模块名")); 示例中有一个输出模块名的步骤,我舍去了 | |
// 设置前缀名 | |
pc.setParent("com.generator"); | |
mpg.setPackageInfo(pc); | |
String myName = scanner("数据名:例(userInfo)"); | |
String myTitle = scanner("模块名:例(用户)"); | |
// 自定义配置 | |
InjectionConfig cfg = new InjectionConfig() { | |
@Override | |
public void initMap() {// 可看作设置了几个全局量,用于将本人模板生成的形容更好,在模板中的应用办法 ${cfg.myName} | |
Map<String, Object> map = new HashMap<>(); | |
map.put("myName", myName); | |
map.put("myTitle", myTitle); | |
this.setMap(map); | |
} | |
}; | |
// 如果模板引擎是 freemarker | |
String templatePath = "/templates/mapper.xml.ftl"; | |
// 自定义输入配置 | |
List<FileOutConfig> focList = new ArrayList<>(); | |
// 自定义配置会被优先输入 | |
focList.add(new FileOutConfig(templatePath) { | |
@Override | |
public String outputFile(TableInfo tableInfo) { | |
// 这里是 resources 里的 mapper.xml | |
return projectPath + "/src/main/resources/mapper/" | |
+ tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;} | |
}); | |
cfg.setFileOutConfigList(focList); | |
mpg.setCfg(cfg); | |
// 配置模板 | |
TemplateConfig templateConfig = new TemplateConfig(); | |
// 配置自定义输入模板, 不写上面的代码就是应用默认的模板输入。// 模板地位找到 mybatis-plus-generator 包关上 templates,上面还会有一张图 | |
templateConfig.setService("templates/service2.java"); | |
templateConfig.setController("templates/controller2.java"); | |
templateConfig.setServiceImpl("templates/serviceImpl2.java"); | |
templateConfig.setMapper("templates/mapper2.java"); | |
// 如果向生成的 xml 里也有代码设置门路,我没有设置 | |
templateConfig.setXml(null); | |
mpg.setTemplate(templateConfig); | |
// 策略配置,骆峰这类的设置 | |
StrategyConfig strategy = new StrategyConfig(); | |
strategy.setNaming(NamingStrategy.underline_to_camel); | |
strategy.setColumnNaming(NamingStrategy.underline_to_camel); | |
// 抉择是否有父类实体 | |
String ipt = scanner("请输出是否抉择父类实体,1 为没有,否则请输出父类"); | |
if (!("1".equals(ipt))) { | |
// 设置父类实体 | |
strategy.setSuperEntityClass(ipt); | |
} | |
// 是否应用 Lombok 的形式 | |
strategy.setEntityLombokModel(true); | |
// 是否应用 RestController | |
strategy.setRestControllerStyle(true); | |
// 公共父类 strategy.setSuperControllerClass("你本人的父类控制器, 没有就不必设置!"); | |
// 写于父类中的公共字段 | |
strategy.setSuperEntityColumns("id"); | |
// 输出相干的名称 | |
strategy.setInclude(scanner("表名,多个英文逗号宰割").split(",")); | |
strategy.setControllerMappingHyphenStyle(true); | |
strategy.setTablePrefix(pc.getModuleName() + "_"); | |
mpg.setStrategy(strategy); | |
mpg.setTemplateEngine(new FreemarkerTemplateEngine()); | |
mpg.execute();} | |
} |
默认模板地位
运行示例
最初放上模板代码
将模板放入 resources 下的 templates 里
controller2.java.ftl
package ${package.Controller}; | |
// 这个中央请本人改变,改成本人的门路 | |
import com.generator.entity.RespBody; | |
import com.generator.entity.${entity}; | |
import com.generator.service.${table.serviceName}; | |
import com.github.pagehelper.PageInfo; | |
import io.swagger.annotations.Api; | |
import io.swagger.annotations.ApiOperation; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.web.bind.annotation.RequestMapping; | |
import org.springframework.web.bind.annotation.RequestMethod; | |
import org.springframework.web.bind.annotation.RequestParam; | |
import java.util.List; | |
<#if restControllerStyle> | |
import org.springframework.web.bind.annotation.RestController; | |
<#else> | |
import org.springframework.stereotype.Controller; | |
</#if> | |
<#if superControllerClassPackage??> | |
import ${superControllerClassPackage}; | |
</#if> | |
/** | |
* <p> | |
* ${table.comment!} 前端控制器 | |
* </p> | |
* | |
* @author ${author} | |
* @since ${date} | |
*/ | |
@Api(tags = "${table.controllerName}", description = "${cfg.myTitle} 治理") | |
<#if restControllerStyle> | |
@RestController | |
<#else> | |
@Controller | |
</#if> | |
@RequestMapping("<#if package.ModuleName??>/${package.ModuleName}</#if>/<#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}</#if>") | |
<#if kotlin> | |
class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}()</#if> | |
<#else> | |
<#if superControllerClass??> | |
public class ${table.controllerName} extends ${superControllerClass} { | |
<#else> | |
public class ${table.controllerName} { | |
</#if> | |
@Autowired | |
private ${table.serviceName} ${cfg.myName}Service; | |
@ApiOperation("查问 ${cfg.myTitle}") | |
@RequestMapping(value = "/list", method = RequestMethod.GET) | |
public RespBody find${entity}(${entity} ${cfg.myName}, | |
@RequestParam(value = "pageStart",defaultValue = "1")Integer pageStart, | |
@RequestParam(value = "pageSize", defaultValue = "10")Integer pageSize){List<${entity}> ${cfg.myName}List = ${cfg.myName}Service.find${entity}(${cfg.myName}, pageStart, pageSize); | |
PageInfo<${entity}> pageInfo = new PageInfo<>(${cfg.myName}List); | |
return RespBody.ok(pageInfo); | |
} | |
@ApiOperation("增加 ${cfg.myTitle}") | |
@RequestMapping(value = "/insert", method = RequestMethod.POST) | |
public RespBody insert${entity}(${entity} ${cfg.myName}) {int result = ${cfg.myName}Service.insert${entity}(${cfg.myName}); | |
if (result == 1) {return RespBody.ok(); | |
} | |
return RespBody.error();} | |
@ApiOperation("批改 ${cfg.myTitle}") | |
@RequestMapping(value = "/update", method = RequestMethod.POST) | |
public RespBody update${entity}(${entity} ${cfg.myName}) {int result = ${cfg.myName}Service.update${entity}(${cfg.myName}); | |
if (result == 1) {return RespBody.ok(); | |
} | |
return RespBody.error();} | |
@ApiOperation("删除 ${cfg.myTitle}") | |
@RequestMapping(value = "/delete", method = RequestMethod.DELETE) | |
public RespBody update${entity}(@RequestParam("id")int id) {int result = ${cfg.myName}Service.delete${entity}(id); | |
if (result == 1) {return RespBody.ok(); | |
} | |
return RespBody.error();} | |
} | |
</#if> |
service2.java.ftl
package ${package.Service}; | |
import ${package.Entity}.${entity}; | |
import ${superServiceClassPackage}; | |
import java.util.List; | |
/** | |
* <p> | |
* ${table.comment!} 服务类 | |
* </p> | |
* | |
* @author ${author} | |
* @since ${date} | |
*/ | |
<#if kotlin> | |
interface ${table.serviceName} : ${superServiceClass}<${entity}> | |
<#else> | |
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> { | |
/** | |
* 查找 ${cfg.myName} | |
* @param ${cfg.myName} | |
* @param pageStart | |
* @param pageSize | |
* @return | |
*/ | |
List<${entity}> find${entity}(${entity} ${cfg.myName}, Integer pageStart, Integer pageSize); | |
/** | |
* 增加 ${cfg.myName} | |
* @param ${cfg.myName} | |
* @return | |
*/ | |
int insert${entity}(${entity} ${cfg.myName}); | |
/** | |
* 批改 ${cfg.myName} | |
* @param ${cfg.myName} | |
* @return | |
*/ | |
int update${entity}(${entity} ${cfg.myName}); | |
/** | |
* 删除 ${cfg.myName} | |
* @param id | |
* @return | |
*/ | |
int delete${entity}(int id); | |
} | |
</#if> |
serviceImpl2.java.ftl
package ${package.ServiceImpl}; | |
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |
import com.github.pagehelper.PageHelper; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import java.util.List; | |
import ${package.Entity}.${entity}; | |
import ${package.Mapper}.${table.mapperName}; | |
import ${package.Service}.${table.serviceName}; | |
import ${superServiceImplClassPackage}; | |
import org.springframework.stereotype.Service; | |
/** | |
* <p> | |
* ${table.comment!} 服务实现类 | |
* </p> | |
* | |
* @author ${author} | |
* @since ${date} | |
*/ | |
@Service | |
<#if kotlin> | |
open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} { | |
} | |
<#else> | |
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}> implements ${table.serviceName} { | |
@Autowired | |
private ${table.mapperName} ${cfg.myName}Mapper; | |
@Override | |
public List<${entity}> find${entity}(${entity} ${cfg.myName}, Integer pageStart, Integer pageSize) { | |
// 这里依据具体的条件进行裁减 | |
QueryWrapper<${entity}> queryWrapper=new QueryWrapper<>(${cfg.myName}); | |
PageHelper.startPage(pageStart,pageSize); | |
return ${cfg.myName}Mapper.selectList(queryWrapper); | |
} | |
@Override | |
public int insert${entity}(${entity} ${cfg.myName}) {return ${cfg.myName}Mapper.insert(${cfg.myName}); | |
} | |
@Override | |
public int update${entity}(${entity} ${cfg.myName}) {return ${cfg.myName}Mapper.updateById(${cfg.myName}); | |
} | |
@Override | |
public int delete${entity}(int id) {return ${cfg.myName}Mapper.deleteById(id); | |
} | |
} | |
</#if> |
mapper2.java.ftl
package ${package.Mapper}; | |
import ${package.Entity}.${entity}; | |
import ${superMapperClassPackage}; | |
import org.springframework.stereotype.Repository; | |
/** | |
* <p> | |
* ${table.comment!} Mapper 接口 | |
* </p> | |
* | |
* @author ${author} | |
* @since ${date} | |
*/ | |
<#if kotlin> | |
interface ${table.mapperName} : ${superMapperClass}<${entity}> | |
<#else> | |
@Repository | |
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> { | |
} | |
</#if> |
更近一步,相干 api 的应用还是要看官网文档 Mybatis-plus 才能够。
正文完