文章目录
- 快速入门
- 入门案例
- 常见注解
- 常见配置
- 核心功能
- 条件构造器
- 自定义SQL
- IService接口
- 扩展功能
- 代码生成器
- 静态工具
- 逻辑删除
- 枚举处理器
- JSON处理器
- 插件功能
- 分页插件
- 通用分页实体
快速入门
入门案例
初始用户表
在单表查询时候简化了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 {@Autowiredprivate UserMapper userMapper;@Testvoid 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);}@Testvoid testSelectById() {User user = userMapper.selectById(5L);System.out.println("user = " + user);}@Testvoid testQueryByIds() {List<User> users = userMapper.selectBatchIds(List.of(1L, 2L, 3L, 4L));users.forEach(System.out::println);}@Testvoid testUpdateById() {User user = new User();user.setId(5L);user.setBalance(20000);userMapper.updateById(user);}@Testvoid 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测试
@Testvoid 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)
@Testvoid 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 = ?)
@Testvoid 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
@Testvoid 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 {@Autowiredprivate IUserService userService;@Testvoid 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);}@Testvoid 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("新增用户接口")@PostMappingpublic void saveUser(@RequestBody UserFormDTO userFormDTO) {//1.将DTO拷贝到POUser 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批量查询用户接口")@GetMappingpublic 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 {@Overridepublic 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.查需要你用户POList<User> users = iUserService.queryUsers(userQuery.getName(),userQuery.getStatus(),userQuery.getMinBalance(),userQuery.getMaxBalance());//2.把PO拷贝到VOreturn 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.查需要你用户POList<User> users = iUserService.queryUsers(userQuery.getName(),userQuery.getStatus(),userQuery.getMinBalance(),userQuery.getMaxBalance());//2.把PO拷贝到VOreturn BeanUtil.copyToList(users, UserVO.class);}
对Service实现类方法进行修改
@Overridepublic 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实现类
@Overridepublic 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为VOUserVO userVO = BeanUtil.copyProperties(user, UserVO.class);//3.2转地址VOif (CollUtil.isNotEmpty(addresses)) {userVO.setAddress(BeanUtil.copyToList(addresses, AddressVO.class));}return userVO;}
需求2
Controller层
@ApiOperation("根据id批量查询用户接口")@GetMappingpublic List<UserVO> queryUserByIds(@RequestParam("ids") List<Long> ids) {return iUserService.queryUserAndAddressByIds(ids);}
Service实现类
@Overridepublic 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转换地址VOList<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为VOUserVO vo = BeanUtil.copyProperties(user,UserVO.class);list.add(vo);//3.2转换地址VOvo.setAddress(addressMap.get(user.getId()));}return list;}
逻辑删除
枚举处理器
JSON处理器
插件功能
分页插件
通用分页实体
Controller层
@ApiOperation("根据条件分页查询用户接口查询")@GetMapping("/page")public PageDTO<UserVO> queryUserspage(UserQuery userQuery) {return iUserService.queryUserspage(userQuery);}
service实现类
@Overridepublic 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的VOList<UserVO> userVOS = BeanUtil.copyToList(records, UserVO.class);pageDTO.setList(userVOS);//4.返回return pageDTO;}