Skip to main content

基础

官网

常见注解

MyBatisPlus通过扫描实体类,并基于反射实体类信息作为数据库表信息

默认:

  • 类名驼峰转下划线作为表名
  • 名为id的字段作为主键
  • 变量名驼峰转下划线作为表

注释:

  • @TableName:用来指定表名

  • @TableId:用来指定表中的主键字段

    • AUTO:数据库id自增长,**如果不设则用雪花算法填充ID **
    • INPUT:通过set方法自行输入
    • ASSIGN_ID:接口identifierGenerator的方法nextId来生成id,默认实现类为DefaultIdentifierGenerator雪花算法
    @TableId(value="id", type="")
    private Long id;
  • @TableField :用来指定表中的普通字段信息

    • 成员变量名与数据库字段名不一致

    • 成员变量名以is开头,且是布尔值(如果不加注释会被省略is转换成布尔类型

      @TableField("is_married")
      private Boolean isMarried;
    • 成员变量名与数据库关键字冲突

      @TableField("'order'")
      private Integer order;
    • 成员变量如果不是数据库字段

      @TableField(exist = false)
      private String address;

常见配置

MyBatisPlus的配置项继承了MyBatis原生的配置和一些自己特有的配置

mybatis-plus:
type-aliase-package: com.happlay.domain.po # 别名扫描包
mapper-locatinos: "classpath*:/mapper/**/*.xml" # Mapper.xml文件地址,默认值
configuration:
map-underscore-to-camel-case: true # 是否开启下划线和驼峰映射
cache-enabled: false # 是否开启二级缓存
global-config:
db-config:
id-type: assign_id # id为雪花算法生成
update-strategy: not_null # 更新策略:zh

核心功能

条件构造器

MyBatisPlus支持各种复杂的where条件,可以满足日常开发的所有需求

LambdaQueryWrapper

避免上面方法中的硬编码

@Test
void testQueryWrapper() {
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
.select(User::getId, User::getUsername, User::getInfo, User::getBalance)
.like(User::getUsername, "o")
.ge(User::getBalance, 1000);

List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}

QueryWrapper&UpdateWrapper

@Test
void testQueryWrapper() {
QueryWrapper<User> wrapper = new QueryWrapper<User>()
.select("id", "username", "info", "balance")
.like("username", "o")
.ge("balance", 1000);

List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}

@Test
void testUpdateByQueryWrapper() {
// 更新的数据
User user = new User();
user.setBalance(2000);
// 更新的条件
QueryWrapper<User> wrapper = new QueryWrapper<User>();
wrapper.eq("username", "Rose");

// 执行条件
userMapper.update(user, wrapper);
}

@Test
void testUpdateWrapper() {
List<Long> ids = Collections.unmodifiableList(Arrays.asList(1L, 2L, 4L));
UpdateWrapper<User> wrapper = new UpdateWrapper<User>()
.setSql("balance = balance - 200")
.in("id", ids);
// 执行条件
userMapper.update(null, wrapper);
}

自定义SQL

利用MyBatisPlus的Wrapper来构建复杂的Where条件,然后自定义剩下的SQL语句

@Test
void testCustomSqlUpdate() {
List<Long> ids = Collections.unmodifiableList(Arrays.asList(1L, 2L, 4L));
int amount = 200;

LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
.in(User::getId, ids);
// 调用自定义SQL方法 !!!!这是重点
userMapper.updateBalanceByIds(wrapper, amount);
}

UserMapper.java

// 第一个注解必须是`ew`或 @Param(Constants.WRAPPER),规定
void updateBalanceByIds(@Param("ew") LambdaQueryWrapper<User> wrapper, @Param("amount") int amount);

UserMapper.xml

<!-- 更新的SQL语句 -->
<update id="updateBalanceByIds">
UPDATE tb_user SET balance = balance - #{amount} ${ew.customSqlSegment} ------这个是where条件,MybatisPlus中的@MapperScanzhu'j
</update>

Service接口

基础用法

  • 自定义Service接口继承IService接口

    # Service接口
    public inerface IUserService extends IService<实体类> {}
  • 自定义Service实现类,实现自定义接口并继承ServiceImpl类

    # ServiceImpl类
    public class UserServiceImpl extends ServiceImpl<Mapper类, 实体类> implements IUserService {}

基础业务接口

// controller层
@RequiredArgsConstructor // 只会对需要在一开始初始化的数据生成构造函数
public class UserController {

// 不用Autowired因为spring不推荐
private final IUserService userService;
@ApiOperation("新增用户接口")
@PostMapping
public void saveUser(@RequestBody UserFormDTO userDTO) {
// 把DTO拷贝到PO
User user = new User();
BeanUtils.copyProperties(userDTO, user);
// 新增
userService.save(user);
}

@ApiOperation("删除用户接口")
@DeleteMapping("{id}")
public void deleteUserById(@ApiParam("用户id") @PathVariable("id") Long id) {
userService.removeById(id);
}

@ApiOperation("根据id查询用户接口")
@GetMapping("{id}")
public UserVO queryUserById(@ApiParam("用户id") @PathVariable("id") Long id) {
User user = userService.getById(id);
// 拷贝成VO
UserVO userVO = new UserVO();
BeanUtils.copyProperties(user, userVO);
return userVO;
}

@ApiOperation("根据id批量查询用户接口")
@GetMapping
public List<UserVO> queryUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids) {
List<User> users = userService.listByIds(ids);
// 拷贝成VO
return BeanUtil.copyToList(users, UserVO.class);
}

复杂业务接口

Controller层

@ApiOperation("扣减用户余额接口")
@PutMapping("/{id}/deduction/{money}")
public void deductBalance(
@ApiParam("用户id") @PathVariable("id") Long id,
@ApiParam("扣减的金额") @PathVariable("money") Integer money) {
userService.deductBalance(id, money);
}

Service层

// 要自定义deductBalance方法
void deductBalance(Long id, Integer money);

ServiceImpl层

// 实现方法
@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.扣减余额 update tb_user set balance = balance - ?
baseMapper.deductBalance(id, money);
}

Mapper层

// 也可以不用在mapper.xml里写sql语句,直接通过注解完成
// @Update("UPDATE tb_user SET balance = balance - #{money} WHERE id = #{id}")
void deductBalance(@Param("id") Long id, @Param("money") Integer money);

Mapper.xml(如果使用注解可以不写)

<update id="deductBalance">
UPDATE tb_user SET balance = balance - #{money} WHERE id = #{id}
</update>

Lambda方法

LambdaQuery

进行复杂查询

原本实现

Controller层

    @ApiOperation("根据复杂条件查询用户接口")
@GetMapping("/list")
public List<UserVO> queryUser(UserQuery query) {
List<User> users = userService.queryUsers(query.getName(), query.getStatus(), query.getMinBalance(), query.getMaxBalance());
// 拷贝成VO
return BeanUtil.copyToList(users, UserVO.class);
}

Service层

List<User> queryUsers(String name, Integer status, Integer minBalance, Integer maxBalance);

ServiceImpl层

@Override
public List<User> queryUsers(String name, Integer status, Integer minBalance, Integer maxBalance) {
return lambdaQuery()
.like(name != null, User::getUsername, name)
.eq(status != null, User::getStatus, status)
.ge(minBalance != null, User::getBalance, minBalance)
.le(maxBalance != null, User::getBalance, maxBalance)
.list();
}
LambdaUpdate
@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.扣减余额 update tb_user set balance = balance - ?
int remainBalance = user.getBalance() - money;
lambdaUpdate()
.set(User::getBalance, remainBalance)
.set(remainBalance < 0, User::getStatus, 2)
.eq(User::getId, id)
.eq(User::getBalance, user.getBalance()) // 乐观锁,防止多个用户同时在线发生冲突
.update(); // 必须加上才是执行更新语句

}