MybatisPlus学习

文章目录

  • 快速入门
    • 入门案例
    • 常见注解
    • 常见配置
  • 核心功能
    • 条件构造器
    • 自定义SQL
    • IService接口
  • 扩展功能
    • 代码生成器
    • 静态工具
    • 逻辑删除
    • 枚举处理器
    • JSON处理器
  • 插件功能
    • 分页插件
    • 通用分页实体

快速入门

入门案例

初始用户表
MybatisPlus学习_第1张图片

MybatisPlus学习_第2张图片
MybatisPlus学习_第3张图片
MybatisPlus学习_第4张图片
MybatisPlus学习_第5张图片
在单表查询时候简化了Mapper接口与XML的配置统统不需要了

//只需继承mybatis-plus提供的接口,指定对应实体类
public interface UserMapper extends BaseMapper<User> {

}


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mp.mapper.UserMapper">


mapper>

Test类中直接调用Mapper接口继承的方法完成增删改查等操作

package com.itheima.mp.mapper;

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;

@SpringBootTest
class UserMapperTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    void testInsert() {
        User user = new User();
        user.setId(5L);
        user.setUsername("Lucy");
        user.setPassword("123");
        user.setPhone("18688990011");
        user.setBalance(200);
        user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        userMapper.insert(user);
    }

    @Test
    void testSelectById() {
        User user = userMapper.selectById(5L);
        System.out.println("user = " + user);
    }


    @Test
    void testQueryByIds() {
        List<User> users = userMapper.selectBatchIds(List.of(1L, 2L, 3L, 4L));
        users.forEach(System.out::println);
    }

    @Test
    void testUpdateById() {
        User user = new User();
        user.setId(5L);
        user.setBalance(20000);
        userMapper.updateById(user);
    }

    @Test
    void testDeleteUser() {
        userMapper.deleteById(5L);
    }
}

MybatisPlus学习_第6张图片

常见注解

MybatisPlus学习_第7张图片
MybatisPlus学习_第8张图片

注意is开头且为boolean类型的变量名,经过反射会将is省略

@Data
@TableName("tb_user")
public class User {

    /**
     * 用户id
     */
    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     * 用户名
     */
//    @TableField("'username'")
    private String username;

MybatisPlus学习_第9张图片
加上注解,执行testQueryByIds方法可见

10:53:53 DEBUG 21696 --- [           main] c.i.mp.mapper.UserMapper.selectBatchIds  : ==>  
Preparing: SELECT id,'username',phone,info,status,balance,create_time,update_time FROM tb_user WHERE id IN ( ? , ? , ? , ? )

在这里插入图片描述

常见配置

MybatisPlus学习_第10张图片
MybatisPlus学习_第11张图片

核心功能

条件构造器

MybatisPlus学习_第12张图片
MybatisPlus学习_第13张图片
Test测试

    @Test
    void testQueryWrapper() {
        //1.构建查询条件
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .select("id","username","info","balance")
                .like("username", "o")
                .ge("balance", 1000);
        //2.查询
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }
    //输出
    //User(id=3, username=Hope, password=null, phone=null, 
    //info={"age": 25, "intro": "上进青年", "gender": "male"}, status=null, balance=100000, createTime=null, updateTime=null)

MybatisPlus学习_第14张图片

    @Test
    void testUpdateByQueryWrapper() {
        //1.要更新的数据
        User user = new User();
        user.setBalance(2000);
        //2、更新的条件
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .eq("username", "jack");
        //3、执行更新
        userMapper.update(user, wrapper);
    }
    //Preparing: UPDATE tb_user SET balance=? WHERE (username = ?)

在这里插入图片描述
MybatisPlus学习_第15张图片

    @Test
    void testUpdateWrapper() {
        List<Long> ids = List.of(1L,2L,4L);
        UpdateWrapper<User> wrapper = new UpdateWrapper<User>()
                .setSql("balance = balance -200")
                .in("id", ids);
        //3、执行更新
        userMapper.update(null, wrapper);
    }

MybatisPlus学习_第16张图片
MybatisPlus学习_第17张图片
MybatisPlus学习_第18张图片

自定义SQL

MybatisPlus学习_第19张图片
MybatisPlus学习_第20张图片

    @Test
    void testCustomSqlUpdate() {
        //1.更新条件
        List<Long> ids = List.of(1L,2L,4L);
        int amount = 200;
        //2.定义条件
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .in("id",ids);
        //3.调用自定义SQL方法
        userMapper.updateBalanceByIds(wrapper,amount);
    }

创建Mapper接口

    void updateBalanceByIds(@Param(Constants.WRAPPER) QueryWrapper<User> wrapper, @Param("amount") int amount);

XML文件


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mp.mapper.UserMapper">

    <update id="updateBalanceByIds">
        update tb_user set balance = balance - #{amount} ${ew.customSqlSegment}
    update>
mapper>

IService接口

MybatisPlus学习_第21张图片
MybatisPlus学习_第22张图片

创建Service层的接口类和实现类


public interface IUserService extends IService<User> {

}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

}

测试

@SpringBootTest
class IUserServiceTest {
    @Autowired
    private IUserService userService;
    @Test
    void testSaveUser() {
        User user = new User();
        user.setUsername("zhangshuwen");
        user.setPassword("123");
        user.setPhone("18688990011");
        user.setBalance(200);
        user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        userService.save(user);
    }
    @Test
    void testQuery() {
        List<User> users = userService.listByIds(List.of(1L,2L,4L));
        users.forEach(System.out::println);
    }
}

MybatisPlus学习_第23张图片
MybatisPlus学习_第24张图片
Controller层


@Api(tags = "用户管理接口")
@RestController
@RequestMapping("/users")
/**
 * @RequiredArgsConstructor 注解在类上使用时,
 * Lombok会为类中的每个标有 final 或 @NonNull 注解的字段生成一个构造函数参数,
 * 然后在编译时自动生成带有这些参数的构造函数。
 * 这样你就不需要手动编写这个构造函数,Lombok会为你处理。
 */
@RequiredArgsConstructor
public class UserController {

    private final IUserService iUserService;



    @ApiOperation("新增用户接口")
    @PostMapping
    public void saveUser(@RequestBody UserFormDTO userFormDTO) {
        //1.将DTO拷贝到PO
        User user = BeanUtil.copyProperties(userFormDTO, User.class);
        //2.新增
        iUserService.save(user);
    }

    @ApiOperation("删除用户接口")
    @DeleteMapping("/{id}")
    public void saveUser(@PathVariable Long id) {
        iUserService.removeById(id);
    }
    @ApiOperation("根据id查询用户接口")
    @GetMapping("/{id}")
    public UserVO selectUser(@PathVariable Long id) {
        User user = iUserService.getById(id);
        return BeanUtil.copyProperties(user, UserVO.class);
    }
    @ApiOperation("根据id批量查询用户接口")
    @GetMapping
    public List<UserVO> queryUserByIds(@RequestParam("ids") List<Long> ids) {
        List<User> users = iUserService.listByIds(ids);
        return BeanUtil.copyToList(users, UserVO.class);
    }
    @ApiOperation("扣减用户余额")
    @PutMapping("/{id}/deduction/{money}")
    public void deductMoneyId(@PathVariable("id") Long id,
                                      @PathVariable("money") Integer money) {
        iUserService.deductBalance(id,money);
    }

}

Service实现类

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Override
    public void deductBalance(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);
    }

Mapper接口

    @Update("update tb_user set balance = balance - #{money} where id = #{id}")
    void deductBalance(@Param("id") Long id, @Param("money") Integer money);

MybatisPlus学习_第25张图片
MybatisPlus学习_第26张图片
Controller接口

    @ApiOperation("根据复杂条件查询")
    @GetMapping("/list")
    public List<UserVO> queryUsers(UserQuery userQuery) {
        //1.查需要你用户PO
        List<User> users = iUserService.queryUsers(userQuery.getName(),userQuery.getStatus(),userQuery.getMinBalance(),userQuery.getMaxBalance());
        //2.把PO拷贝到VO
        return BeanUtil.copyToList(users, UserVO.class);
    }

Service实现类

    /**
     * lambdaQuery(): 这是 MyBatis-Plus 提供的静态方法,用于创建一个 LambdaQueryWrapper 对象,LambdaQueryWrapper 是 MyBatis-Plus 中的查询条件构造器,允许通过 lambda 表达式动态构建查询条件。
     *
     * .like(name!=null, User::getUsername, name): 这一行表示如果 name 不为 null,则添加一个模糊查询条件,查询条件是 User 对象的 getUsername 方法返回的字段,且字段值与传入的 name 相匹配。
     *
     * .eq(status!=null, User::getStatus, status): 这一行表示如果 status 不为 null,则添加一个等于查询条件,查询条件是 User 对象的 getStatus 方法返回的字段,且字段值与传入的 status 相等。
     *
     * .ge(minBalance!=null, User::getBalance, minBalance): 这一行表示如果 minBalance 不为 null,则添加一个大于等于查询条件,查询条件是 User 对象的 getBalance 方法返回的字段,且字段值大于等于传入的 minBalance。
     *
     * .le(maxBalance!=null, User::getBalance, maxBalance): 这一行表示如果 maxBalance 不为 null,则添加一个小于等于查询条件,查询条件是 User 对象的 getBalance 方法返回的字段,且字段值小于等于传入的 maxBalance。

     */
    @ApiOperation("根据复杂条件查询")
    @GetMapping("/list")
    public List<UserVO> queryUsers(UserQuery userQuery) {
        //1.查需要你用户PO
        List<User> users = iUserService.queryUsers(userQuery.getName(),userQuery.getStatus(),userQuery.getMinBalance(),userQuery.getMaxBalance());
        //2.把PO拷贝到VO
        return BeanUtil.copyToList(users, UserVO.class);
    }

MybatisPlus学习_第27张图片
对Service实现类方法进行修改

    @Override
    public void deductBalance(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.扣减余额
        int remainBalance = user.getBalance() - money;
        lambdaUpdate()
                .set(User::getStatus,remainBalance)
                .set(remainBalance==0, User::getStatus,2)
                .eq(User::getId,id)
                .eq(User::getBalance,user.getBalance())  //乐观锁防止并发错误
                .update();
    }

扩展功能

代码生成器

MybatisPlus学习_第28张图片
在idea中通过mybatis-plus插件生成代码
MybatisPlus学习_第29张图片
分别点击两个选项完成配置数据库配置信息
在这里插入图片描述
MybatisPlus学习_第30张图片

MybatisPlus学习_第31张图片

静态工具

MybatisPlus学习_第32张图片
MybatisPlus学习_第33张图片
静态工具类(如 MyBatis-Plus 中的 SqlHelper)和 IService 接口在具体开发与实际使用中有一些区别,主要取决于它们的设计目的和使用场景:

设计目的:

静态工具类: 静态工具类的设计目的是提供一些通用的静态方法,用于执行底层的 SQL
操作或其他常见操作。这些方法通常是静态的,无需创建对象实例,用于简化底层操作。 IService 接口: IService 接口及其实现类
ServiceImpl 的设计目的是为了提供一些通用的 CRUD(增删改查)操作,封装常见的业务逻辑,提供了一种面向对象的服务层抽象。

使用场景:

静态工具类: 静态工具类适用于一些不涉及对象实例状态的操作,例如执行 SQL 查询,文件操作等。这些方法通常是静态的,可以通过类名直接调用。
IService 接口: IService 接口适用于业务服务层的抽象,封装了一些通用的业务操作,特别是针对实体对象的 CRUD
操作。IService 接口可以被业务层的服务类实现,提供具体的业务逻辑。

需求1
Controller层

    @GetMapping("/{id}")
    public UserVO selectUser(@PathVariable Long id) {
        return iUserService.queryUsersAndAddressById(id);
    }

Service实现类

    @Override
    public UserVO queryUsersAndAddressById(Long id) {
        //1.查询用户
        User user = getById(id);
        if (user == null || user.getStatus() == 2){
            throw new RuntimeException("用户状态异常!");
        }
        //2.查询地址
        List<Address> addresses = Db.lambdaQuery(Address.class)
                .eq(Address::getUserId, id).list();

        //3.封装VO
        //3.1装User的PO为VO
        UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
        //3.2转地址VO
        if (CollUtil.isNotEmpty(addresses)) {
            userVO.setAddress(BeanUtil.copyToList(addresses, AddressVO.class));
        }
        return userVO;
    }

需求2
Controller层

    @ApiOperation("根据id批量查询用户接口")
    @GetMapping
    public List<UserVO> queryUserByIds(@RequestParam("ids") List<Long> ids) {

        return iUserService.queryUserAndAddressByIds(ids);
    }

Service实现类

    @Override
    public List<UserVO> queryUserAndAddressByIds(List<Long> ids) {
        //1.查询用户
        List<User> users = listByIds(ids);
        if (CollUtil.isEmpty(users)){
            return Collections.emptyList();
        }
        //2.查询地址
        //2.1 获取用户id集合
        List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());
        //2.2根据用户id查询地址
        List<Address> addresses = Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list();
        //2.3转换地址VO
        List<AddressVO> addressVOList = BeanUtil.copyToList(addresses, AddressVO.class);
        //2.4梳理地址集合,分类整理,相同用户的放入同一个集合中
        Map<Long, List<AddressVO>> addressMap = new HashMap<>();
        if (CollUtil.isNotEmpty(addressVOList)){
            addressMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));
        }

        //3.转VO返回
        List<UserVO> list = new ArrayList<>(users.size());
        for (User user : users){
            //3.1转换User的PO为VO
            UserVO vo = BeanUtil.copyProperties(user,UserVO.class);
            list.add(vo);
            //3.2转换地址VO
            vo.setAddress(addressMap.get(user.getId()));
        }
        return list;
    }

逻辑删除

MybatisPlus学习_第34张图片MybatisPlus学习_第35张图片

枚举处理器

MybatisPlus学习_第36张图片

MybatisPlus学习_第37张图片
MybatisPlus学习_第38张图片

JSON处理器

MybatisPlus学习_第39张图片

插件功能

分页插件

MybatisPlus学习_第40张图片
MybatisPlus学习_第41张图片
MybatisPlus学习_第42张图片

通用分页实体

MybatisPlus学习_第43张图片
Controller层

    @ApiOperation("根据条件分页查询用户接口查询")
    @GetMapping("/page")
    public PageDTO<UserVO> queryUserspage(UserQuery userQuery) {
        return iUserService.queryUserspage(userQuery);
    }

service实现类

    @Override
    public PageDTO<UserVO> queryUserspage(UserQuery userQuery) {
        String name = userQuery.getName();
        Integer status = userQuery.getStatus();
        //1.构建查询条件
        //1.1分页条件
        Page<User> page = Page.of(userQuery.getPageNo(), userQuery.getPageSize());
        //1.2排序条件
        if (StrUtil.isNotBlank(userQuery.getSortBy())){
            //不为空
            page.addOrder(new OrderItem(userQuery.getSortBy(),userQuery.getIsAsc()));
        }else {
            //为空,默认按照更新时间排序
            page.addOrder(new OrderItem("update_time",false));
        }
        //2.分页查询
        Page<User> userPage = lambdaQuery()
                .like(name != null, User::getUsername, name)
                .eq(status != null, User::getStatus, status)
                .page(page);
        //3.封装VO结果
        PageDTO<UserVO> pageDTO = new PageDTO<>();
        //3.1总条数和总页数
        pageDTO.setTotal(userPage.getTotal());
        pageDTO.setPages(userPage.getPages());
        //当前页数据
        List<User> records = userPage.getRecords();
        if (CollUtil.isEmpty(records)){
            pageDTO.setList(Collections.emptyList());
            return pageDTO;
        }
        //拷贝User的VO
        List<UserVO> userVOS = BeanUtil.copyToList(records, UserVO.class);
        pageDTO.setList(userVOS);
        //4.返回
        return pageDTO;
    }

你可能感兴趣的:(Java,学习,spring,boot,mybatis-plus)