MyBatis‑Plus Service 层常用自带方法
前提:你的
UserServiceImpl继承了ServiceImpl<UserMapper, User>
所以所有这些方法,在你的service实现类里面可以直接调用,不用写 mapper、不用写sql。
@ServicepublicclassUserServiceImplextendsServiceImpl<UserMapper,User>implementsIUserService{"这里就能直接用 query()、save()、updateById() ..."}两套API区分清楚:
1️⃣Service链式(LambdaQuery / query()):query().eq().one()
2️⃣Service普通方法:save、saveBatch、updateById、removeById、getById
3️⃣ Mapper层方法:userMapper.selectById()(不推荐在service优先使用)
一、查询类(最常用)
1. query() 链式条件查询【黑马点评在用】
query() 返回一个查询构造器,支持链式拼接条件
page(current, size)
请看 query().page(current, size)
one() 查询一条
// where phone = 13800138000Useruser=query().eq("phone","13800138000").one();- 查到1条 → 返回对象
- 查到0条 → null
- 查到≥2条 →抛异常
list() 查询多条,返回集合
// 查询状态为正常的所有用户List<User>userList=query().eq("status",1).list();count() 统计条数
// 查询手机号是否已经存在longcount=query().eq("phone","13800138000").count();if(count>0){//手机号已注册}getOne(Wrapper) 老版写法(不推荐链式以外的)
现在优先用 query()
lambdaQuery() 👉【生产环境强烈推荐!!】
query()写字符串字段名"phone",拼写错不会编译报错!lambdaQuery()用实体属性,编译校验,不会写错
Useruser=lambdaQuery().eq(User::getPhone,"13800138000").one();List<User>list=lambdaQuery().eq(User::getStatus,1).list();✅企业开发优先 lambdaQuery(),少用 query()
条件方法对照表(链式里面 .之后调用)
| 方法 | 含义 | 生成SQL |
|---|---|---|
.eq("字段",值) | 等于 | phone = ? |
.ne("字段",值) | 不等于 | phone <> ? |
.gt("age",18) | 大于 | age > 18 |
.ge("age",18) | 大于等于 | age >=18 |
.lt("age",18) | 小于 | age < 18 |
.le("age",18) | 小于等于 | age <= 18 |
.like("name","张") | 模糊查询 %张% | name like '%张%' |
.likeLeft("name","三") | %三 | name like '%三' |
.likeRight("name","张") | 张% | name like '张%' |
.in("id", 1,2,3) | id在集合里面 | id in (1,2,3) |
.isNull("email") | 字段为null | email is null |
.isNotNull("email") | 不为null | email is not null |
.orderByDesc("id") | id降序 | order by id desc |
.orderByAsc("id") | id升序 | order by id asc |
示例,多条件组合:
List<User>list=lambdaQuery().eq(User::getStatus,1).like(User::getNickName,"张").ge(User::getAge,18).orderByDesc(User::getId).list();2. getById(id) 根据主键id查询(超级高频)
// 根据主键id查用户Useruser=getById(1L);- 查到返回对象,查不到返回null
3. listByIds() 根据多个id批量查询
List<Long>idList=Arrays.asList(1L,2L,3L);List<User>userList=listByIds(idList);4. list() 不带条件 → 查询整张表全部数据
⚠️ 数据量大禁止使用!!
List<User>all=list();二、新增类
1. save(entity) 单条新增
Useruser=newUser();user.setPhone("13800138000");user.setNickName("user_abc");//插入一条数据booleansuccess=save(user);- 返回 boolean,true插入成功
- 主键如果是自增,插入成功后,user对象里面id会自动回填!
2. saveBatch() 批量新增(一次插入多条)
List<User>addList=newArrayList<>();addList.add(newUser());addList.add(newUser());//批量插入booleanok=saveBatch(addList);三、修改更新类
后期的详细补充
1. updateById(entity) 根据主键id更新(最常用)
只更新
实体中非null的字段!!!大坑重点
Useruser=newUser();user.setId(1L);user.setNickName("新名字");// 根据id更新昵称booleanok=updateById(user);生成SQL:update user set nick_name=? where id=?
不会把其他字段置空!只更新你设置过的属性
2. update(实体, 更新条件Wrapper) 条件更新
MP 只会更新实体中你 set 过、不为 null 的字段。
你只setNickName,所以只会更新nick_name,其他字段完全不动,不会被清空。
按条件更新,不是根据主键
// 把所有 status=0 的用户,昵称改成游客UserupdateEntity=newUser();updateEntity.setNickName("游客");booleanok=update(updateEntity,lambdaUpdate().eq(User::getStatus,0));lambdaUpdate() 链式构建更新条件
四、删除类
1. removeById(id) 根据主键删除
booleanok=removeById(1L);2. remove(条件Wrapper) 按条件删除
//删除手机号为空的用户booleanok=remove(lambdaQuery().isNull(User::getPhone));3. removeByIds() 批量删除多个id
List<Long>ids=Arrays.asList(1L,2L);booleanok=removeByIds(ids);⚠️实际业务几乎不做物理删除!用逻辑删除,加字段
is_deleted
五、分页查询 - 高频
"pageNum当前页,pageSize每页条数"Page<User>page=newPage<>(1,5);// 分页查询,状态为1的用户Page<User>resultPage=page(page,lambdaQuery().eq(User::getStatus,1));// 获取分页数据List<User>records=resultPage.getRecords();// 总条数longtotal=resultPage.getTotal();⚠️分页功能必须配置MyBatis‑Plus分页拦截器,否则分页失效!
六、一张速查表:Service层高频方法
| 方法 | 作用 |
|---|---|
getById(id) | 主键id查单条 |
save(entity) | 新增一条 |
updateById(entity) | 根据主键更新 |
removeById(id) | 主键删除 |
query().eq().one() | 条件查一条(字符串字段) |
lambdaQuery().eq().one() | 条件查一条【推荐】 |
lambdaQuery().eq().list() | 条件查列表 |
lambdaQuery().count() | 条件统计数量 |
lambdaUpdate() | 链式条件更新 |
page(page,wrapper) | 分页查询 |
七、容易踩的4个坑(高频出错)
坑1:updateById 只更新非null字段
如果你写:
Useruser=newUser();user.setId(1L);// 没有设置nickNameupdateById(user);只会更新id,其他字段不动,不会清空。
坑2:one() 查到多条抛异常
如果你用手机号查询,数据库如果不小心存了两条相同手机号,one()直接崩溃。
坑3:query(“phone”)字符串写错,运行时报错,编译不报红
👉解决:生产一律优先lambdaQuery(User::getPhone)
坑4:MP的save不会自动给你填创建时间、更新时间
需要自动填充(createTime、updateTime),要用MetaObjectHandler