Mybatis-Plus
大家学习的时候可以参照官网简介 | MyBatis-Plus
目录
基本流程
1.在pom.xml导入依赖
2.给自己的类继承父类
3.常见注解
4.常见配置
核心功能
1.条件构造器
2.自定义sql
3.IService接口
扩展功能
1.代码生成器
2.Db静态工具
3.逻辑删除
4.枚举处理器
5.JSON处理器
插件功能
基本流程
1.在pom.xml导入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
2.给自己的类继承父类
之后测试类就可以直接用了,直接用类的Mapper点,然后挑选方法
3.常见注解
1.可以用这个来指定表名,在这个例子中,表的名字和类名字不一样,所以要用这个注解。
2.这个是用来表示主键的注解,type来定义属性,自增长
3.这个是因为表里面属性的名字和类的属性名字不一致,需要用这个注解
4.同3
5.order是关键字,所以需要转义重新命名
6.此属性在表里面不存在,所以需要用到exit这个属性
4.常见配置
在application.yaml里面配置
核心功能
1.条件构造器
1.查询名字带o,余额大于1000的
void testQueryWrapper() {
//构建查询条件
QueryWrapper<User> wrapper=new QueryWrapper<User>()
.select("id,username,balance,info")
.like("username","o")
.ge("balance",1000);
//查询
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
-
QueryWrapper<User>
泛型为User
,表示这是一个针对User
实体类的查询条件构造器。 -
.select("id,username,balance,info")
指定查询的字段(若省略,默认查询所有字段SELECT *
)。 -
.like("username", "o")
生成username LIKE '%o%'
的模糊查询条件。 -
.ge("balance", 1000)
生成balance >= 1000
的范围查询条件。
-
userMapper.selectList(wrapper)
调用 MyBatis-Plus 的selectList
方法,传入QueryWrapper
对象,执行查询并返回符合条件的User
列表。
2.更新用户名字为jack的余额为2000
@Test
void testUpdateQueryWrapper() {
User user = new User();
user.setBalance(2000);
//构建查询条件
QueryWrapper<User> wrapper=new QueryWrapper<User>()
.eq("username","jack");
//查询
userMapper.update(user,wrapper);
}
这段代码的作用是找到用户名为"jack"的用户,并仅更新该用户的余额(balance
)至2000。其他未设置的字段不会受到影响,因为MyBatis Plus默认只会更新你明确设置了值的字段。不过,这依赖于MyBatis Plus的版本和配置,确保你使用的版本支持这种行为。
3.将id 为 1 2 4用户的余额扣200
@Test
void testUpdateWrapper() {
List <Long> ids=List.of(1L,2L,4L);
//构建查询条件
UpdateWrapper<User> wrapper=new UpdateWrapper<User>()
.setSql("balance =balance-200")
.in("id",ids);
//查询
userMapper.update(null,wrapper);
}
2.自定义sql
@Test
void testUpdateWrapper() {
List <Long> ids=List.of(1L,2L,4L);
int amount=200;
//构建查询条件
LambdaUpdateWrapper<User> wrapper=new LambdaUpdateWrapper<User>()
.in(User::getId,ids);
//查询
userMapper.updatebalance(wrapper,amount);
}
public interface UserMapper extends BaseMapper<User> {
//一定要加注解 ew amount
void updatebalance(@Param("ew") LambdaUpdateWrapper<User> wrapper, @Param("amount") int amount);
}
<update id="updatebalance">
UPDATE user SET balance= balance-#{amount} ${ew.customSqlSegment}
</update>
3.IService接口
本质还是调用mapper
按照下面创建接口和实现类,然后接口继承
IService<User>
然后实现类继承
ServiceImpl<UserMapper, User>
UserMapper是用到的mapper,因为本质还是调用mapper,User是你要操作的类
实现接口
接口
package com.itheima.mp.Service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.mp.domain.po.User;
public interface IUserService extends IService<User> {
}
实现类
package com.itheima.mp.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.mp.Service.IUserService;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.mapper.UserMapper;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}
给接口创建一个测试类
package com.itheima.mp.Service;
import com.itheima.mp.domain.po.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.time.LocalDateTime;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class IUserServiceTest {
@Autowired
private IUserService userService;
@Test
void testSaveUser() {
User user = new User();
user.setId(6L);
user.setUsername("lilei");
user.setPassword("123");
user.setPhone("18688996666");
user.setBalance(200);
user.setInfo("{\"age\": 25, \"intro\": \"地理老师\", \"gender\": \"male\"}");
user.setCreateTime(LocalDateTime.now());
user.setUpdateTime(LocalDateTime.now());
userService.save(user);
}
@Test
void testQuery() {
List<User> users = userService.listByIds(List.of(1L, 2L, 3L, 4L));
users.forEach(System.out::println);
}
}
业务接口
新建controlller,在里面写各个接口
package com.itheima.mp.controller;
import cn.hutool.core.bean.BeanUtil;
import com.itheima.mp.Service.IUserService;
import com.itheima.mp.domain.dto.UserFormDTO;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.vo.UserVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.Tag;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.service.Tags;
import java.util.List;
@RequestMapping("/users")
@RestController
@Api(tags="用户管理接口")
public class UserControlller {
@Autowired
private IUserService userService;
@ApiOperation("新增用户接口")
@PostMapping
public void saveUser(@RequestBody UserFormDTO userDTO){
User user = BeanUtil.copyProperties(userDTO, User.class);
userService.save(user);
}
@ApiOperation("删除用户接口")
@DeleteMapping("{id}}")
public void deleteUserById(@ApiParam("用户id") @PathVariable("id") Long id){
userService.removeById(id);
}
@ApiOperation("查询单个用户接口")
@GetMapping("{id}}")
public UserVO queryUserById(@ApiParam("用户id") @PathVariable("id") Long id){
User user=userService.getById(id);
return BeanUtil.copyProperties(user, UserVO.class);
}
@ApiOperation("查询多个用户接口")
@GetMapping
public List<UserVO> queryUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids){
List<User> users=userService.listByIds(ids);
return BeanUtil.copyToList(users, UserVO.class);
}
@ApiOperation("扣减单个用户余额接口")
@GetMapping("/{id}}/deduction/{money}")
public void deducteMoneyById(
@ApiParam("用户id") @PathVariable("id") Long id,
@ApiParam("扣减的钱") @PathVariable("money") Integer money
){
userService.deducteById(id,money);
}
}
其中,最后一个接口,业务复杂,mp的iservice没有符合这个功能的方法,所以要自己定义
在接口中定义
然后在实现类里面定义
package com.itheima.mp.Service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.mp.Service.IUserService;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.mapper.UserMapper;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
@Override
public void deducteById(Long id, Integer money) {
// 1. 查询用户
User user = getById(id);
// 2. 校验用户状态
if(user==null||user.getStatus()==2){
throw new RuntimeException("用户状态异常");
}
// 3. 校验余额是否充足
if(user.getBalance()<money){
throw new RuntimeException("用户余额不足");
}
// 4. 扣减余额
baseMapper.deductBalance(id,money);
//此处也可以使用条件构造器
}
}
- 继承
ServiceImpl
后,你无需手动注入 Mapper 接口(如UserMapper
),因为baseMapper
已经提供了对它的访问。
通过baseMapper来访问UserMapper
UserMapper.java
package com.itheima.mp.mapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.mp.domain.po.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserMapper extends BaseMapper<User> {
//一定要加注解 ew amount
void updatebalance(@Param("ew") LambdaUpdateWrapper<User> wrapper, @Param("amount") int amount);
void deductBalance(@Param("id")Long id, @Param("money")Integer money);
}
UserMapper.xml
<update id="deductBalance">
UPDATE user SET balance= balance-#{money} where id=#{id}
</update>
当你使用 MyBatis-Plus 的 lambdaUpdate()
方法时,实际上是通过动态构建 SQL 语句,并最终调用 BaseMapper
中的基础方法来执行数据库操作。
有 更新的 lambdaUpdate 后面要加 .update();
有 查询的 lambdaQuery
扩展功能
1.代码生成器
要安装一个插件
2.Db静态工具
可能service会互相注入,循环注入,所以使用静态工具避免循环注入
3.逻辑删除
因为有时候某个数据很重要,不能直接删除,所以定义一个属性可以标记他是否被删除,就不用真的删除,当你需要找他的时候,就根据这个标记的属性来查询(比如0是未被删除,1是被删除)
首先你的表里面要有某个字段作为逻辑删除的标记字段
在yaml里面配置逻辑删除字段
mybatis-plus:
global-config:
db-config:
logic-delete-field: deleted # 全局逻辑删除的实体字段名
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
就可以了
package com.itheima.mp.Service;
import com.itheima.mp.domain.po.Address;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class IAddressServiceTest {
@Autowired
private IAddressService addressService;
@Test
void testDeleteByLogic() {
// 删除方法与以前没有区别
addressService.removeById(59L);
//查询
Address address = addressService.getById(59L);
System.out.println("address = " + address);
}
}
4.枚举处理器
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
package com.itheima.mp.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;
@Getter
public enum UserStatus {
NORMAL(1, "正常"),
FREEZE(2, "冻结");
@EnumValue
private final int value;
@JsonValue
private final String desc;
UserStatus(int value, String desc) {
this.value = value;
this.desc = desc;
}
}
5.JSON处理器
表里面有字段是json类型的数据,处理JSON就可以使用JacksonTypeHandler
处理器。