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才可以。