MybatisPlus学习

快速入门

入门案例

初始用户表
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在单表查询时候简化了Mapper接口与XML的配置统统不需要了

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

}

<?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.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);
    }
}

在这里插入图片描述

常见注解

在这里插入图片描述
在这里插入图片描述

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

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

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

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

在这里插入图片描述
加上注解,执行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 ( ? , ? , ? , ? )

在这里插入图片描述

常见配置

在这里插入图片描述
在这里插入图片描述

核心功能

条件构造器

在这里插入图片描述
在这里插入图片描述
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)

在这里插入图片描述

    @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 = ?)

在这里插入图片描述
在这里插入图片描述

    @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);
    }

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

自定义SQL

在这里插入图片描述
在这里插入图片描述

    @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文件

<?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.itheima.mp.mapper.UserMapper">
<!--${ew.customSqlSegment}: 这是 MyBatis-Plus 中的动态 SQL 语句的一部分。
它表示在运行时将替换为由QueryWrapper(ew)对象定义的条件部分。
${} 是动态 SQL 中的变量占位符,表示在运行时替换为实际的 SQL 片段。-->
    <update id="updateBalanceByIds">
        update tb_user set balance = balance - #{amount} ${ew.customSqlSegment}
    </update>
</mapper>

IService接口

在这里插入图片描述
在这里插入图片描述

创建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);
    }
}

在这里插入图片描述
在这里插入图片描述
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);

在这里插入图片描述
在这里插入图片描述
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);
    }

在这里插入图片描述
对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();
    }

扩展功能

代码生成器

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

在这里插入图片描述

静态工具

在这里插入图片描述
在这里插入图片描述
静态工具类(如 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;
    }

逻辑删除

在这里插入图片描述在这里插入图片描述

枚举处理器

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

JSON处理器

在这里插入图片描述

插件功能

分页插件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

通用分页实体

在这里插入图片描述
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;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jimmy Ding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值