MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
以SpringBoot为例,导入依赖:
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.5.5version>
dependency>
数据库配置如下
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring_data?characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
示例代码如下:
@TableName("user")
public class User {
private Integer id;
private String name;
private String age;
//getter and setter
}
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
@SpringBootApplication
@MapperScan("com.example.mybatisstudy.dao")//扫描mapper
public class MybatisStudyApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisStudyApplication.class, args);
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test {
@Autowired
private UserMapper userMapper;
@org.junit.Test
public void testSelect() {
System.out.println(("----- selectAll method test ------"));
List<User> userList = userMapper.selectList(null);
userList.forEach(System.out::println);
}
}
效果如图

从以上步骤中,我们可以看到集成MyBatis-Plus非常的简单,只需要引入 starter 工程,并配置 mapper 扫描路径即可。甚至连 XML 文件都不用编写!
@TableName:表名注解,标识实体类对应的表@TableName("user")
public class User {
private Integer id;
private String name;
private String age;
//getter and setter
}
注解更多属性如图:

@TableId:主键注解@TableName("user")
public class User {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
}
types属性指定主键类型,默认IdType.NONE。

@TableField:字段注解(非主键)@TableName("user")
public class User {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
@TableField(value = "name")
private String name;
}
注解更多属性如图:

@Version:乐观锁注解、标记在字段上。@TableName("user")
public class User {
@TableId(value = "id",type = IdType.AUTO)
@Version
private Integer id;
}
然后注册Bean
@Configuration
public class MyConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
}
@EnumValue:普通枚举类注解。@TableName("user")
public class User {
@TableId(value = "id",type = IdType.AUTO)
@Version
private Integer id;
@EnumValue
private String type;
}
@TableLogic:表字段逻辑处理注解(逻辑删除)。@TableName("user")
public class User {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
@TableField(value = "name")
@TableLogic(value = "a",delval = "b")
private String name;
}
value属性表示逻辑未删除值,delval属性表示逻辑删除值。
@KeySequence:于指定插入操作返回自增主键值的注解。在 MyBatis 中,有些数据库(如 Oracle)并不是像 MySQL 那样具有自增长主键的功能,而是通过序列(sequence)来生成主键值。@TableName("user")
@KeySequence(value = "id",dbType = DbType.MYSQL)
public class User {
}
@InterceptorIgnore:用于指定是否在某个方法上忽略拦截器的注解。@Intercepts({
@Signature(
type= Executor.class,
method = "update",
args = {MappedStatement.class,Object.class}
)
})
public class ExampleInterceptor implements Interceptor {
// 实现拦截器的逻辑
// ...
}
public interface UserMapper {
@InterceptorIgnore
@Insert("INSERT INTO users (id, name) VALUES (#{id}, #{name})")
int insertUser(User user);
}
@OrderBy:指定查询操作的结果集的排序规则。@TableName("user")
public class User {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@TableField(value = "name")
private String name;
@OrderBy(asc = true)
private String age;
}
引入依赖
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-generatorartifactId>
<version>3.5.5version>
dependency>
<dependency>
<groupId>org.apache.velocitygroupId>
<artifactId>velocity-engine-coreartifactId>
<version>2.0version>
dependency>
示例代码如下:
public class Test {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/spring_data", "root", "123456")
// 全局配置
.globalConfig((scanner, builder) -> {
builder.author(scanner.apply("请输入作者名称?"));
// 获取用户的当前工作目录
String userDir = System.getProperty("user.dir");
builder.outputDir(userDir+"\\src\\main\\java\\"); // 指定输出目录
})
// 包配置
.packageConfig((scanner, builder) -> builder.parent(scanner.apply("请输入包名?")))
// 策略配置
.strategyConfig((scanner, builder) -> builder.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all")))
.controllerBuilder().enableRestStyle().enableHyphenStyle()
.entityBuilder().enableLombok().addTableFills(
new Column("create_time", FieldFill.INSERT)
).build())
/*
模板引擎配置,默认 Velocity 可选模板引擎 Beetl 或 Freemarker
.templateEngine(new BeetlTemplateEngine())
.templateEngine(new FreemarkerTemplateEngine())
*/
.execute();
}
// 处理 all 情况
protected static List<String> getTables(String tables){
return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
}
}
改进后,会自动生成到当前项目中,如图所示

Service CRUD 封装IService (opens new window)接口,进一步封装 CRUD 采用 get 查询单行 remove 删除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆,
public interface IUserService extends IService<User> {
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}
数据插入,如果数据已存在则报错
// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量),batchSize:插入批次数量
boolean saveBatch(Collection<T> entityList, int batchSize);
示例代码如下:
@Controller
public class MyController {
@Autowired
private IUserService iUserService;
@GetMapping("/get")
public void get(HttpServletResponse response){
User user = new User();
user.setId(9);
user.setName("f");
user.setAge("23");
boolean b = iUserService.save(user);
System.out.println(b);
/** Output
* true
*/
}
}
先查询,数据库存在则更新记录,否插入一条记录
// TableId 注解存在更新记录,否插入一条记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新(类似条件)
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
示例代码如下:
@Controller
public class MyController {
@Autowired
private IUserService iUserService;
@GetMapping("/get")
public void get(HttpServletResponse response){
User user = new User();
user.setId(6);
user.setName("f");
user.setAge("23");
boolean b = iUserService.saveOrUpdate(user);
User user2 = new User();
user2.setId(8);
user2.setName("g");
user2.setAge("23");
boolean b2 = iUserService.saveOrUpdate(user2);
}
}
如图所示:

数据删除
// 根据 queryWrapper 设置的条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);
示例代码如下:
@Controller
public class MyController {
@Autowired
private IUserService iUserService;
@GetMapping("/get")
public void get(HttpServletResponse response){
boolean b = iUserService.removeById(7);
boolean b2 = iUserService.removeByIds(Arrays.asList(1,2,3,4));
}
}
数据更新
// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据 whereWrapper 条件,更新记录
boolean update(T updateEntity, Wrapper<T> whereWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);
示例代码如下:
@Controller
public class MyController {
@Autowired
private IUserService iUserService;
@GetMapping("/get")
public void get(HttpServletResponse response){
User user = new User();
user.setId(6);user.setName("f");
user.setAge("23");
boolean b = iUserService.updateById(user);
System.out.println(b);
/** Output
* true
*/
}
}
获取单条数据
// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
示例代码如下:
@Controller
public class MyController {
@Autowired
private IUserService iUserService;
@GetMapping("/get")
public void get(HttpServletResponse response){
User user = iUserService.getById(1);
System.out.println(user.toString());
/** Output
* {id:1,name:a,age:12}
*/
}
}
获取列表数据
// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查询所有列表
List<Map<String, Object>> listMaps();
// 查询列表
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查询全部记录
List<Object> listObjs();
// 查询全部记录
<V> List<V> listObjs(Function<? super Object, V> mapper);
// 根据 Wrapper 条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
示例代码如下:
@Controller
public class MyController {
@Autowired
private IUserService iUserService;
@GetMapping("/get")
public void get(HttpServletResponse response){
List<User> list = iUserService.list();
System.out.println(list.toString());
System.out.println("===========================");
Map<String, Object> map= new HashMap<>();
map.put("name","a");
List<User> list2 = iUserService.listByMap(map);
System.out.println(list2.toString());
System.out.println("===========================");
List<User> list3 = iUserService.listByIds(Arrays.asList(1,2,3,4));
System.out.println(list3.toString());
/** Output
* [{id:1,name:a,age:12}, {id:2,name:b,age:13}, {id:3,name:c,age:14}, {id:4,name:bb,age:15}, {id:5,name:ee,age:22}, {id:6,name:null,age:2}, {id:7,name:f,age:2}]
* ===========================
* [{id:1,name:a,age:12}]
* ===========================
* [{id:1,name:a,age:12}, {id:2,name:b,age:13}, {id:3,name:c,age:14}, {id:4,name:bb,age:15}]
*/
}
}
你需要配置分页拦截器:
@Configuration
public class MyConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return mybatisPlusInterceptor;
}
}
调用page()方法进行分页
// 无条件分页查询
IPage<T> page(IPage<T> page);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 无条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);
Page对象一共有四个构造方法,可以用来定义分页的页数和条数,你也可以调用对应的set方法进行赋值。
//传入页数、条数
public Page(long current, long size) {}
//传入页数、条数、总数
public Page(long current, long size, long total) {}
//传入页数、条数、是否查询总数:true是、false否
public Page(long current, long size, boolean searchCount) {}
//传入页数、条数、总数、是否查询总数:true是、false否
public Page(long current, long size, long total, boolean searchCount) {}
示例代码如下:
@Controller
public class MyController {
@Autowired
private IUserService iUserService;
@GetMapping("/get")
public void get(HttpServletResponse response){
Page<User> userPage = new Page<>(1,3,true);
Page<User> p = iUserService.page(userPage);
List<User> records = p.getRecords();
System.out.println(records.toString());
/** Output
* [{id:1,name:a,age:12}, {id:2,name:b,age:13}, {id:3,name:c,age:14}]
*/
}
}
当searchCount属性为true的情况,会先去查询总数后分页。

查询总数
// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);
示例代码如下:
@Controller
public class MyController {
@Autowired
private IUserService iUserService;
@GetMapping("/get")
public void get(HttpServletResponse response){
long count = iUserService.count();
System.out.println(count);
/** Output
* 8
*/
}
}
关于Wrapper对象的使用在稍后的章节里详细讲解。
实体类只需继承 Model 类即可进行强大的 CRUD 操作
class User extends Model<User>{
// fields...
public static void main(String[] args) {
User user = new User();
user.insert();
user.selectAll();
user.updateById();
user.deleteById();
// ...
}
}
不过在开发过程中,业务逻辑通过自动注入进行操作,实体类只用于数据传输操作。
通过封装BaseMapper (opens new window)接口实现CRUD操作。
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
新增数据
int insert(T entity);
示例代码如下:
@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
User user = new User();
user.setId(10);
user.setName("h");
user.setAge("23");
long insert = userMapper.insert(user);
System.out.println(insert);
/** Output
* 1
*/
}
}
删除数据
// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 ID 删除
int deleteById(Serializable id);
// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
示例代码如下:
@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
//根据ID删除
int deleteById = userMapper.deleteById(1);
//根据ID批量删除
int deleteById2 = userMapper.deleteBatchIds(Arrays.asList(1, 2, 3, 4));
//根据key=value当做条件删除
Map<String,Object> map = new HashMap<>();
map.put("name","g");
int deleteById3 = userMapper.deleteByMap(map);
}
}
修改数据
// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
// 根据 ID 修改
int updateById(@Param(Constants.ENTITY) T entity);
示例代码如下:
@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
User user = new User();
user.setId(10);
user.setName("h");
user.setAge("23");
long insert = userMapper.updateById(user);
}
}
查询数据
// 根据 ID 查询
T selectById(Serializable id);
// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据 columnMap 条件)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
示例代码如下:
@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
//传null查询全部
List<User> users = userMapper.selectList(null);
//通过id查询
User user = userMapper.selectById(1);
//批量id查询
List<User> users2 = userMapper.selectBatchIds(Arrays.asList(1,2,3,4));
//根据key=value当做条件查询
Map<String,Object> map = new HashMap<>();
map.put("name","g");
map.put("age","23");
List<User> users3 = userMapper.selectByMap(map);
}
}
再CRUD的方法中,看到很多的Wrapper参数,下面就来学习如何使用它当中参数。
QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类,用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件。
QueryWrapper 是 MyBatis-Plus 中的一个查询条件构造器,用于构建查询条件。使用 QueryWrapper 可以实现复杂的查询条件组合,例如等值条件、范围条件、模糊查询、排序等。QueryWrapper 还支持 Lambda 表达式,可以通过 Lambda 来指定字段名,减少因为字段改名而引起的错误。
使用select方法,指定查询返回字段。
@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.select("id","name");
List<User> users = userMapper.selectList(wrapper);
}
}
如图所示

UpdateWrapper 是 MyBatis-Plus 中用于构建更新操作条件的类,使用set()方法设置要更新的字段及对应的数值。
@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.eq("id","7");
wrapper.set("name","g");
wrapper.set("age","20");
int users = userMapper.update(wrapper);
}
}
如图所示

传入Map参数,key为数据库字段名,value为字段值。
allEq(Map<R, V> params)
//null2IsNull:忽略空值
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
示例代码如下:
@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
Map<String,Object> map = new HashMap<>();
map.put("name","a");
map.put("age",null);
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.allEq(map);
List<User> users = userMapper.selectList(wrapper);
System.out.println(users.toString());
wrapper = new QueryWrapper<>();
wrapper.allEq(map,false);
List<User> users2 = userMapper.selectList(wrapper);
System.out.println(users2.toString());
/** Output
* []
* [{id:1,name:a,age:12}]
*/
}
}
执行结果如图

=@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name","a");
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图所示

<>@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.ne("name","a");
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图所示

>@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age",21);
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

>=@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.ge("age",21);
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

<@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.lt("age",21);
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

<=@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.le("age",21);
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

BETWEEN 值1 AND 值2@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.between("age",21,25);
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

NOT BETWEEN 值1 AND 值2@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.notBetween("age",21,25);
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

LIKE '%值%'@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("name","b");
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

NOT LIKE '%值%'@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.notLike("name","b");
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

LIKE '%值'@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.likeLeft("name","b");
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

LIKE '值%'@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.likeRight("name","b");
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

NOT LIKE '%值'@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.notLikeLeft("name","b");
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

NOT LIKE '值%'@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.notLikeRight("name","b");
List<User> users14 = userMapper.selectList(wrapper);
}
}
执行结果如图

@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.isNull("name");
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.isNotNull("name");
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

字段 IN (value.get(0), value.get(1), ...)@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.in("id",1,2,3,4,5);
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

字段 NOT IN (value.get(0), value.get(1), ...)@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.notIn("id",1,2,3,4,5);
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

字段 IN ( sql语句 )@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.inSql("id","select id from user where age <23");
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

字段 NOT IN ( sql语句 )@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.notInSql("id","select id from user where age <23");
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

GROUP BY 字段, ...@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.groupBy("class_id");
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

ORDER BY 字段, ... ASC@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.orderByAsc("id");
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

ORDER BY 字段, ... DESC@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.orderByDesc("id");
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

HAVING ( sql语句 )@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.groupBy("class_id");
wrapper.having("age >20");
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

使用 QueryWrapper 的 and() 和 or() 方法可以实现多个查询条件的组合
@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.isNotNull("name")
.and(w1 -> w1.like("name", "a").eq("age", "12"))
.or(w2 -> w2.eq("name", "b").ge("age", "20"));
List<User> users = userMapper.selectList(wrapper);
}
}
如图所示

EXISTS ( sql语句 )@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.exists("select * from user where id = 1");
List<User> users = userMapper.selectList(wrapper);
}
}
执行结果如图

NOT EXISTS ( sql语句 )@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.notExists("select * from user where id = 1");
List<User> users2 = userMapper.selectList(wrapper);
}
}
执行结果如图

我们可以使用多个条件来过滤数据,从而得到符合多个条件的结果。
@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("id",1);
wrapper.eq("name","a");
wrapper.eq("age","12");
List<User> users = userMapper.selectList(wrapper);
}
}
如图所示

在实际的应用中,经常会遇到根据不同条件动态构建查询条件的情况。
@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
String name = null;
String age = "12";
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("id",1);
if(name != null) {
wrapper.eq("name", name);
}
if(age != null) {
wrapper.eq("age", age);
}
List<User> users = userMapper.selectList(wrapper);
}
}
如图所示

如果你要使用XML,需要加上配置文件进行扫描
在 MyBatis-Plus 中,主键策略可以通过 @TableId 注解来指定。主键生成策略有多种选择,常用的有如下几种:
@TableName("user")
public class User {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String name;
private String age;
}
@TableName("user")
public class User {
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Integer id;
private String name;
private String age;
}
@TableName("user")
public class User {
@TableId(value = "id", type = IdType.ASSIGN_UUID)
private Integer id;
private String name;
private String age;
}
@TableName("user")
public class User {
@TableId(value = "id", type = IdType.INPUT)
private Integer id;
private String name;
private String age;
}
自定义生成类
@Component
public class CustomIdGenerator implements IdentifierGenerator {
@Override
public Long nextId(Object entity) {
//可以将当前传入的class全类名来作为bizKey,或者提取参数来生成bizKey进行分布式Id调用生成.
String bizKey = entity.getClass().getName();
//根据bizKey调用分布式ID生成
long id = ....;
//返回生成的id值即可.
return id;
}
}
注入bean,两种方法
@Bean
public IdentifierGenerator idGenerator() {
return new CustomIdGenerator();
}
或者通过 MybatisPlusPropertiesCustomizer 自定义
@Bean
public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {
return plusProperties -> plusProperties.getGlobalConfig().setIdentifierGenerator(new CustomIdGenerator());
}
内置支持:DB2KeyGenerator、H2KeyGenerator、KingbaseKeyGenerator、OracleKeyGenerator、PostgreKeyGenerator。
@Bean
public IKeyGenerator keyGenerator() {
return new H2KeyGenerator();
}
逻辑删除是指在数据库中并不真正删除数据记录,而是通过标记一个字段来表示数据记录的删除状态,通常是将该字段的值设置为已删除的标识。
有两种方法可以使用逻辑删除:全局配置和指定注解
在配置文件中添加全局配置
# 逻辑已删除值(默认为 1)
mybatis-plus.global-config.db-config.logic-delete-value=1
# 逻辑未删除值(默认为 0)
mybatis-plus.global-config.db-config.logic-not-delete-value=0
找到实体类字段,加上注解@TableLogic
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private String age;
private Integer classId;
@TableLogic
private Integer isDel;
@Override
public String toString() {
return "{id:"+id+",name:"+name+",age:"+age+"}";
}
}
你可以直接使用注解进行设置
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private String age;
private Integer classId;
@TableLogic(value = "0",delval = "1")
private Integer isDel;
@Override
public String toString() {
return "{id:"+id+",name:"+name+",age:"+age+"}";
}
}
如果没有配置属性值,默认情况下value = "0",delval = "1"
加上注解后对应的CRUD操作会有一些变化:
@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
User user = new User();
user.setId(8);
user.setName("g");
user.setAge("15");
userMapper.insert(user);
}
}
如图所示

where 条件过滤掉已删除数据。@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
User user = userMapper.selectById(1);
}
}
如图所示

where 条件防止更新到已删除数据。@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
User user = new User();
user.setId(8);
user.setName("g");
user.setAge("15");
userMapper.updateById(user);
}
}
如图所示

@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
userMapper.deleteById(8);
}
}
如图所示

自动填充功能可以用于在插入和更新操作时自动填充一些字段的值,比如创建时间、更新时间、操作人等。可以通过实现 MetaObjectHandler 接口来实现
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
LocalDateTime currentTime = LocalDateTime.now();
this.strictInsertFill(metaObject, "ctime", LocalDateTime.class, currentTime);
this.strictInsertFill(metaObject, "utime", LocalDateTime.class, currentTime);
}
@Override
public void updateFill(MetaObject metaObject) {
LocalDateTime currentTime = LocalDateTime.now();
this.strictUpdateFill(metaObject, "utime", LocalDateTime.class, currentTime);
}
}
实体类加上注解@TableField(fill = FieldFill.*)
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private String age;
private Integer classId;
private Integer isDel;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime ctime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime utime;
@Override
public String toString() {
return "{id:"+id+",name:"+name+",age:"+age+"}";
}
}
我们分别执行新增和修改操作
@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
User user = new User();
user.setId(8);
user.setName("g");
user.setAge("15");
userMapper.insert(user);
}
}
如图所示

@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
User user = new User();
user.setId(8);
user.setName("g");
user.setAge("15");
userMapper.updateById(user);
}
}
如图所示

可以看到执行新增和修改操作时都自动填充了相应的值。
FieldFill是一个枚举,有以下几种值:
public enum FieldFill {
/**
* 默认不处理
*/
DEFAULT,
/**
* 插入填充字段
*/
INSERT,
/**
* 更新填充字段
*/
UPDATE,
/**
* 插入和更新填充字段
*/
INSERT_UPDATE
}
注入MybatisPlusInterceptor类,并配置BlockAttackInnerInterceptor拦截器
@Configuration
public class MyConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
return interceptor;
}
}
@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@GetMapping("/get")
public void get(HttpServletResponse response){
User user = new User();
user.setId(8);
user.setName("g");
user.setAge("15");
userMapper.update(user,null);
}
}
执行结果如图所示

MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。
安装方法:打开 IDEA,进入 File -> Settings -> Plugins -> Browse Repositories,输入 mybatisx 搜索并安装。

找到Idea最右侧,数据库连接,点击新建,输入用户名密码等信息,创建Mysql连接。

填写完毕后,点击Apply按钮。
按下列图顺序,选择显示的数据库

找到对应的表

点击MybatisX-Generator,填写路径和包名,点击下一步

然后选择Myabtis-Plus 3的相关操作,按图片勾选,点击Finish

生成效果如下
