MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
· 无侵入: 只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
· 损耗小: 启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
· 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
· 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
· 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
· 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
· 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
· 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
· 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
· 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
· 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
· 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
任何能使用 mybatis 进行 crud, 并且支持标准 sql 的数据库
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<!--逆向工程需要模板引擎(自定义模板)-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
<!-- 代码生成默认模板(必须) -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
# MySQL数据源配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/db_name?serverTimezone=Hongkong
username: root
password: password
# MyBatis Plus配置-可以忽略加载映射文件
mybatis-plus:
mapper-locations: classpath:mapper/**/*Mapper.xml #映射文件
type-aliases-package: com.mybatisPlus.entity # 持久化所在位置
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
id-type: 0
field-strategy: 2
capital-mode: true
refresh-mapper: true
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class CodeGenerateUtil {
/**
* 读取控制台内容
*/
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.setOutputDir("dir:\\xxx");
// 自己的署名
gc.setAuthor("code Lin");
gc.setOpen(false);
gc.setSwagger2(true); //实体属性 Swagger2 注解
gc.setServiceName("%sService");
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/db_name?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("password");
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName(null);
pc.setParent("com.mybatisPlus.demo");
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
// 如果模板引擎是 freemarker
String templatePath = "/templates/mapper.xml.ftl";
// 如果模板引擎是 velocity
// String templatePath = "/templates/mapper.xml.vm";
// 自定义输出配置
List<FileOutConfig> focList = new ArrayList<>();
// 自定义配置会被优先输出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
return projectPath + "/src/main/resources/mapper/"
+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);
strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
strategy.setControllerMappingHyphenStyle(true);
// 设置表前缀
strategy.setTablePrefix("tb_");
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}
/**
*
* Student对象
*
*
* @author code Lin
* @since 2021-01-07
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="Student对象", description="")
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String studentName;
private String email;
private Integer gender;
private Integer age;
}
/**
*
* Mapper 接口
*
*
* @author code Lin
* @since 2021-01-07
*/
public interface StudentMapper extends BaseMapper<Student> {
}
/**
* 新增
*/
@Test
public void insert(){
Student student_new = new Student();
student_new.setAge(12);
student_new.setEmail("[email protected]");
student_new.setGender(3);
student_new.setStudentName("小桂子");
int insert = studentMapper.insert(student_new);
if (insert > 0) {
System.out.println("insert: success");
}
}
/**
* 更新
*/
@Test
public void update(){
// 先查询出来亦可
// Student student = studentMapper.selectById(7);
Student student = new Student();
student.setId(8);
student.setStudentName("如来佛祖");
studentMapper.updateById(student);
}
/**
* 删除
*/
@Test
public void delete(){
Student student = new Student();
student.setId(8);
if (studentMapper.deleteById(student.getId()) > 0) {
System.out.println("delete: success");
}
}
6.1 查询全部数据
@Test
public void selectList() {
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
List<Student> students = studentMapper.selectList(studentQueryWrapper);
students.forEach(System.out :: println);
System.out.println("students: QueryWrapper: " + students);
}
6.2 模糊查询
like() - ‘%%’
likeLeft() - ’ %’
likeRight() - '% ’
notLike() - !
/**
* 模糊查询
*/
@Test
public void selectListLike() {
String name = "悟";
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
studentQueryWrapper.like("student_name",name);
List<Student> students1 = studentMapper.selectList(studentQueryWrapper);
System.out.println("模糊查询 :" + students1);
System.out.println("模糊查询第一个对象 :" + students1.get(0));
System.out.println("模糊查询第一个对象名称 :" + students1.get(0).getStudentName());
}
6.3 复合查询
综合用法:or(),and(),inSql() … (各种搭配着来)
/**
* 复合查询
*/
@Test
public void selectRecombination() {
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
studentQueryWrapper.inSql("gender","select gender from student where gender = 1").or(st -> st.between("age",22,33));
List<Student> students1 = studentMapper.selectList(studentQueryWrapper);
System.out.println("复合查询结果:" + students1);
System.out.println("复合查询结果长度:" + students1.size());
}
6.4 单个查询
/**
* 单个查询
*/
@Test
public void selectByIdTest() {
Student student = studentMapper.selectById(7);
System.out.println("student = " + student);
}
/**
*
* 古诗词 前端控制器
*
*
* @author code Lin
* @since 2021-01-08
*/
@RestController
@RequestMapping("/ancient-poetry")
public class AncientPoetryController {
@Autowired
private AncientPoetryService ancientPoetryService;
@Autowired
private AncientPoetryMapper ancientPoetryMapper;
@RequestMapping("/selectList")
public List<AncientPoetry> selectList() {
return ancientPoetryService.list();
}
@RequestMapping("/selectAncientPoetry")
@ResponseBody
@ApiOperation(value = "查询 普通")
public List<AncientPoetry> selectAncientPoetry(@RequestParam String name, AncientPoetry ancientPoetry) {
QueryWrapper<AncientPoetry> queryWrapper = new QueryWrapper<>(ancientPoetry);
queryWrapper.like("chapters", name);
return ancientPoetryService.list(queryWrapper);
}
@RequestMapping("/selectPage")
@ResponseBody
@ApiOperation(value = "查询 分页")
public Page<AncientPoetry> selectPage(@RequestParam Integer page, @RequestParam Integer pageSize, @RequestParam(required = false) String name, AncientPoetry ancientPoetry) {
Page<AncientPoetry> ancientPoetryPage = new Page<>();
ancientPoetryPage.setCurrent(page);
ancientPoetryPage.setSize(pageSize);
QueryWrapper<AncientPoetry> ancientPoetryQueryWrapper = new QueryWrapper<>(ancientPoetry);
if (StringUtils.isNotBlank(name)) {
ancientPoetryQueryWrapper.like("chapters", name);
}
return ancientPoetryService.page(ancientPoetryPage, ancientPoetryQueryWrapper);
}
@RequestMapping("/selectChain")
@ResponseBody
@ApiOperation(value = "链式查询 普通")
public List<AncientPoetry> selectChain(@RequestParam(required = false) String name, AncientPoetry ancientPoetry) {
QueryChainWrapper<AncientPoetry> ancientPoetryQueryWrapper = new QueryChainWrapper<>(ancientPoetryMapper);
if (StringUtils.isNotBlank(name)) {
ancientPoetryQueryWrapper.like("chapters", name);
}
return ancientPoetryQueryWrapper.list();
}
@RequestMapping("/selectLambdaChain")
@ResponseBody
@ApiOperation(value = "链式查询 lambda 式。注意:不支持 Kotlin")
public List<AncientPoetry> selectLambdaChain(@RequestParam(required = false) String name, AncientPoetry ancientPoetry) {
LambdaQueryChainWrapper<AncientPoetry> lambdaQueryChainWrapper = new LambdaQueryChainWrapper<>(ancientPoetryMapper);
if (StringUtils.isNotBlank(name)) {
// condition 查询条件 是否启用
lambdaQueryChainWrapper.like(false, AncientPoetry::getChapters, name);
}
return lambdaQueryChainWrapper.list();
}
@RequestMapping("/updateChain")
@ResponseBody
@ApiOperation(value = "链式更新 普通")
public boolean updateChain(@RequestParam(required = false) String title, AncientPoetry ancientPoetry) {
UpdateChainWrapper<AncientPoetry> updateChainWrapper = new UpdateChainWrapper<>(ancientPoetryMapper);
return updateChainWrapper.eq("id", ancientPoetry.getId()).update(ancientPoetry);
}
@RequestMapping("/updateLambdaChain")
@ResponseBody
@ApiOperation(value = "链式更新 lambda 式。注意:不支持 Kotlin")
public boolean updateLambdaChain(@RequestParam(required = false) String name, AncientPoetry ancientPoetry) {
LambdaUpdateChainWrapper<AncientPoetry> lambdaUpdateChainWrapper = new LambdaUpdateChainWrapper<>(ancientPoetryMapper);
lambdaUpdateChainWrapper.eq(AncientPoetry::getId, ancientPoetry.getId());
return lambdaUpdateChainWrapper.eq(AncientPoetry::getId, ancientPoetry.getId()).update(ancientPoetry);
}
}
Mybatis_Plus 为开发提供巨大的便捷性,提高开发的效率,正如官方所描述的那样:在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。