基础
官网
常见注解
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(); // 必须加上才是执行更新语句
}