Appearance
MyBatis-Plus
导入依赖
org.springframework.boot:spring-boot-starter:3.1.5
org.springframework.boot:spring-boot-starter-web:3.1.5
com.baomidou:mybatis-plus-boot-starter:3.5.4
快速入门
java
package com.futureweaver.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.futureweaver.po.Dept;
public interface DeptMapper extends BaseMapper<Dept> {
}
java
@TableName("deptinfo")
public class Dept {
@TableId(value="deptid", type=IdType.AUTO)
private Integer deptno;
@TableField("deptname")
private String dname;
@TableField("deptloc")
private String loc;
// ...
}
CRUD
BaseMapper核心接口
java
/**
* Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
*/
public interface BaseMapper<T> extends Mapper<T> {
/**
* 插入一条记录
* @param entity 实体对象
*/
int insert(T entity);
/**
* 根据 ID 删除
* @param id 主键ID
*/
int deleteById(Serializable id);
/**
* 根据实体(ID)删除
* @param entity 实体对象
*/
int deleteById(T entity);
/**
* 根据 columnMap 条件,删除记录
* @param columnMap 表字段 map 对象
*/
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
/**
* 根据 entity 条件,删除记录
* @param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 删除(根据ID或实体 批量删除)
* @param idList 主键ID列表或实体列表(不能为 null 以及 empty)
*/
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<?> idList);
/**
* 根据 ID 修改
* @param entity 实体对象
*/
int updateById(@Param(Constants.ENTITY) T entity);
/**
* 根据 whereEntity 条件,更新记录
* @param entity 实体对象 (set 条件值,可以为 null)
* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
/**
* 根据 ID 查询
* @param id 主键ID
*/
T selectById(Serializable id);
/**
* 查询(根据ID 批量查询)
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
/**
* 查询(根据 columnMap 条件)
* @param columnMap 表字段 map 对象
*/
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
/**
* 根据 entity 条件,查询一条记录
* <p>查询一条记录,例如 qw.last("limit 1") 限制取一条记录, 注意:多条数据会报异常</p>
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
default T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper) {
List<T> ts = this.selectList(queryWrapper);
if (CollectionUtils.isNotEmpty(ts)) {
if (ts.size() != 1) {
throw ExceptionUtils.mpe("One record is expected, but the query result is multiple records");
}
return ts.get(0);
}
return null;
}
/**
* 根据 Wrapper 条件,判断是否存在记录
* @param queryWrapper 实体对象封装操作类
* @return
*/
default boolean exists(Wrapper<T> queryWrapper) {
Long count = this.selectCount(queryWrapper);
return null != count && count > 0;
}
/**
* 根据 Wrapper 条件,查询总记录数
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
Long selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
* <p>注意: 只返回第一个字段的值</p>
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录(并翻页)
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
<P extends IPage<T>> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录(并翻页)
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类
*/
<P extends IPage<Map<String, Object>>> P selectMapsPage(P page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
}
基础增删改查
java
//@TableName("dept")
public class Dept {
@TableId(type=IdType.AUTO)
private Integer deptno;
// @TableField("dname")
private String dname;
// @TableField("loc")
private String loc;
// ...
}
java
package com.futureweaver;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.futureweaver.mapper.DeptMapper;
import com.futureweaver.po.Dept;
@SpringBootTest
class SmpApplicationTests {
@Autowired
private DeptMapper deptMapper;
//全查询
@Test
public void testSelect() {
List<Dept> list = deptMapper.selectList(null);
for(Dept dept : list) {
System.out.println(dept);
}
}
//根据主键查询
@Test
public void testSelectById() {
//注意:根据ID查询时要指定主键生成策略
Dept dept = deptMapper.selectById(41);
System.out.println(dept);
}
//插入
@Test
public void testInsert() {
//注意:Insert时要指定主键生成策略
int result = deptMapper.insert(new Dept(null,"技术部","沈阳市"));
System.out.println(result);
}
//更新
@Test
public void testUpdate() {
int result = deptMapper.updateById(new Dept(45,"财务部","沈阳市"));
System.out.println(result);
}
//删除
@Test
public void testDelete() {
int result = deptMapper.deleteById(46);
System.out.println(result);
}
}
QueryWrapper入门
MyBatis-plus封装了条件构造器 QueryWrapper,用于进行多条件的查询、更新、删除(insert不需要条件)。
java
@Test
public void testQueryWrapper() {
QueryWrapper qw = new QueryWrapper();
qw.gt("deptid", 40);
qw.lt("deptId", 44);
qw.like("deptName", "术");
//多条件查询
List<Dept> list = deptMapper.selectList(qw);
for(Dept dept : list) {
System.out.println(dept);
}
//多条件更新
//int result = deptMapper.update(new Dept(null,"aaa","bbb"), qw);
//多条件删除
//int result = deptMapper.delete(qw);
}
- 先创建QueryWrapper对象,然后向此对象中添加多个条件。
- QueryWrapper对象封装了很多方法用于不同的条件,多个条件之间默认使用 and 连接。
- 使用Mapper进行查询时,由于会返回多条记录,所以使用selectList方法,并且将QueryWrapper对象作为参数传入。
- 注意:QueryWrapper对象可以应用在查询、更新和删除中。
运行之后可以查看日志:
shell
[main]: ==> Preparing: SELECT deptId,deptName,deptLoc FROM dept WHERE (deptId > ? AND deptid < ? AND deptname LIKE ?)
[main]: ==> Parameters: 40(Integer), 44(Integer), %术%(String)
[main]: <== Total: 1
QueryWrapper的常用方法
QueryWrapper对象方法 | 描述 |
---|---|
eq | 等于 = |
ne | 不等于 <> |
gt | 大于 > |
ge | 大于等于 >= |
lt | 小于 < |
le | 小于等于 <= |
between | BETWEEN 值1 AND 值2( 例: between("age", 18, 30)) |
like | LIKE '%值%' |
isNull | 字段 IS NULL |
in | 字段 IN ( 例: in("age",{1,2,3})) |
orderBy | 排序 (例: orderBy(true, true, "id", "name")) |
UpdateWrapper的用法
java
@Test
public void testUpdateWrapper() {
UpdateWrapper uw = new UpdateWrapper();
uw.set("deptname", "XX部");
uw.set("deptloc", "YY市");
uw.gt("deptId", 1);
uw.lt("deptId", 3);
uw.like("deptname", "术");
int result = deptMapper.update(null, uw);
System.out.println(result);
}
- 使用uw.set("","")的方式添加更新数据,这样在deptMapper.update(null, uw);中只需要传递一个uw即可。
生成的sql语句如下
shell
UPDATE dept SET deptname=?,deptloc=? WHERE (deptId > ? AND deptId < ? AND deptname LIKE ?)
分页查询
通过MyBatis-plus提供的自动分页插件:PaginationInnerInterceptor,就可以方便的实现分页功能。
- 在主启动类同包下,创建MyBatis-plus配置类
java
package com.futureweaver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
- 使用 BaseMapper 中的selectPage方法实现分页查询
java
package com.futureweaver;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.futureweaver.mapper.DeptMapper;
import com.futureweaver.po.Dept;
@SpringBootTest
class MpApplicationTests {
@Autowired
private DeptMapper deptMapper;
@Test
public void testPage() {
//创建IPage对象,设置参数:第几页、每页显示最大行数
IPage<Dept> page = new Page<>(3, 4);
//调用selectPage方法进行分页查询,返回值为IPage对象。
IPage<Dept> deptPage = deptMapper.selectPage(page, null);
//通过IPage对象获取当前满足条件总行数
System.out.println(deptPage.getTotal());
//通过IPage对象获取每页显示最大条数
System.out.println(deptPage.getSize());
//通过IPage对象获取当前页
System.out.println(deptPage.getCurrent());
//通过IPage对象获取当前分页总页数
System.out.println(deptPage.getPages());
//通过IPage对象获取业务数据
List<Dept> list = deptPage.getRecords();
for(Dept dept : list) {
System.out.println(dept);
}
}
}
其它复杂操作
当然,我们在实际开发中会遇到很多复杂操作,比如:多表连接查询,批量操作等等。此时官方推荐我们使用Mapper映射文件来书写复杂的SQL语句,就像是在MyBatis中一样。
- 在application.yml配置文件中添加配置:
yaml
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.futureweaver.po
- 在Mapper接口中添加方法
java
package com.futureweaver.mapper;
import org.apache.ibatis.annotations.Mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.futureweaver.po.Dept;
//@Mapper //也可以在主启动类中使用@MapperScan注解统一引入
public interface DeptMapper extends BaseMapper<Dept> {
public Dept getDeptById(Integer deptno);
}
- 在 classpath:mapper/*.xml 路径下添加 DeptMapper.xml文件
xml
<?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.futureweaver.mapper.DeptMapper">
<select id="getDeptById" parameterType="int" resultType="Dept">
select * from dept where deptno=#{deptno}
</select>
</mapper>
MyBatis-plus逆向工程
MyBatis-plus逆向工程可以根据数据库结构,自动生成开发中需要的类:controller、service、mapper等等。
- 添加MyBatis-plus逆向工程依赖
xml
<!-- mybatis-plus-generator依赖(这里默认基于FreeMarker模板引擎) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
- 添加逆向工程启动类(注意:下面代码适合于3.5.1版本)
java
package com.futureweaver;
import java.util.Collections;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
public class MyGenerator {
private static final String URL = "jdbc:mysql://localhost:3306/emp?characterEncoding=utf-8";
private static final String USERNAME = "root";
private static final String PASSWORD = "123";
private static final String PACKAGE_NAME = "com.futureweaver";
private static final String AUTHOR_NAME = "zhangsan";
private static final String OUTDIR_JAVA = "D:\\mywork\\mp\\src\\main\\java";
private static final String OUTDIR_XML = "D:\\mywork\\mp\\src\\main\\resources\\mapper";
public static void main(String[] args) {
FastAutoGenerator.create(URL, USERNAME, PASSWORD)
.globalConfig(builder -> {
builder.author(AUTHOR_NAME) // 设置作者
.fileOverride() // 覆盖已生成文件
.outputDir(OUTDIR_JAVA) // 指定输出目录
.disableOpenDir(); // 禁止打开输出目录
})
.packageConfig(builder -> {
builder.parent(PACKAGE_NAME) // 设置包名
.entity("po") //设置实体类包名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, OUTDIR_XML)); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.addInclude("emp") // 设置需要生成的表名
.controllerBuilder() //这里写controllerBuilder,表示将开始controller配置
.enableRestStyle();
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}
- 运行逆向工程类即可生成代码。