这里写目录标题
- Mybatis-plus
Mybatis-plus
- MybatisPlus 对 Mybatis 只做增强不做修改。
- 简单配置,即可快速进行单表 CRUD(增删改查),提高效率。
快速使用
1.引入起步依赖
MybatisPlus 依赖能 代替 Mybatis 依赖
xml
<!--MybatisPlus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
2.继承BaseMapper
为Mapper类继承 BaseMapper<实体类名>
xml
public interface UserMapper extends BaseMapper<User> {
}
3.常见注解
mybatisPlus 中默认约定为
- 类名驼峰 转 下划线 作为 表名
- 名为 id 的字段作为 主键
- 变量名驼峰 转 下划线 作为 表的字段名
TableName
如果不遵守约定就得使用以下注解:
java
@TableName("数据库表名")
public class User {
@TableId(value = "表中主键名")
private Long userid;
}
@TableId
@TableId 属性名 | 作用 |
---|---|
value | 绑定表中主键名 |
type | IdType 枚举 |
:
AUTO:数据库中 主键自增长
:
INPUT:通过 set 方法 自行输入
:
ASSIGN_ID:分配 ID,接口 IdentifierGenerator 的方法 nextId 来生成 id ,默认实现类为 DefaultIdentifierGenerator 雪花算法
@TableField 的常见使用场景
- 成员变量名 与 数据库字段名 不一致
- 成员变量名 以 is 开头,且是 布尔值
- 成员变量名 与 数据库关键字冲突
成员变量 不是数据库字段
java
@TableField("username")
private String name;
@TableField("is_married")
private Boolean isMarried; //为bool值 is会被去除 对应字段名: married
@TableField("`order`")
private Integer order;
@TableField(exist = false)
private String address; // 数据库不使用该属性
4.常见配置
MyBatisPlus 的配置项 继承了 MyBatis原生配置 和一些自己 特有的配置。
yaml
mybatis-plus:
type-aliases-package: com.itheima.mp.domain.po # 别名扫描包
mapper-locations: 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 # 更新策略:只更新非空字段
条件构造器
目的:当查询条件不根据 ID 查询时,就要传入 条件构造器 来查询。
AbstractWrepper
实现SQL中的 where 部分:
函数 | 作用 |
---|---|
eq("列名",值) | = |
ne("列名",值) | != |
gt("列名",值) | > |
ge("列名",值) | >= |
lt("列名",值) | < |
le ("列名",值) | <= |
like | 模糊 |
notLike | 非模糊 |
likeLeft | %在左 |
likeRight | %在右 |
java
// 基于QueryWrapper案例
@Test
void testQueryWrapper(){
//查询name 带 o 的,存款 >= 1000 的 id, username,info,balance
// 1. 构建查询条件 where部分
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);
}
// 基于QueryWrapper案例
@Test
void testUpdateByQueryWrapper(){
//更新 username 为jack 用户 的 余额 为2000
User user = new User(); // set 部分
user.setBalance(2000);
// where 条件
QueryWrapper<User>wrapper=new QueryWrapper<User>().eq("username","jack");
userMapper.update(user,wrapper);
// 要更新的用户 更新条件
}
java
// 基于UpdateWrapper案例
@Test
void testUpdateWrapper(){
List<Long>ids= Collections.unmodifiableList(Arrays.asList(1L,2L,3L));
// update user set balance=balance -200 where id in (1,2,3)
UpdateWrapper<User>wrapper=new UpdateWrapper<User>()
.setSql("balance=balance-200") // set 部分
// .setSql("status=status-1")
.in("id",ids); //where
userMapper.update(null,wrapper);
}
自定义 SQL
可以利用 MyBatisPlus 的 Wrapper 来构建复杂的 Where条件,然后自己定义SQL语句中剩下的部分。
- 基于Wrapper构建 where 条件
java
@Test
void testConstomSqlUpdate(){
List<Long>ins=Collections.unmodifiableList(Arrays.asList(1L,2L,3L));
int amount=200;
QueryWrapper<User>wrapper=new QueryWrapper<User>().in("id",ins);
//传入 条件构建 减少的参数
userMapper.updateBalanceByIds(wrapper,amount);
}
- 在 mapper方法参数中用 @Param() 注解声明 wrapper 变量名称,必须是 ew
java
// Constants 常量 或传入 "ew"
void updateBalanceByIds(@Param(Constants.WRAPPER) QueryWrapper<User> wrapper, @Param("amount") int amount);
- 自定义SQL 并使用 Wrapper 条件
xml
<update id="updateBalanceByIds">
<!-- ew.customSqlSegment 自定义SQL片段-->
update user set balance=balance-#{amount} ${ew.customSqlSegment}
</update>
Service 接口
使用 IService 接口
MP 的 IService 接口中定义了许多业务的实现功能。为了方便使用,所以使用 ServiceImpl 类中实现了 IService接口。
当使用MP框架时,我们可以使用这些功能,来减少代码量。
使用方法为:
-
使用自定义 Service 接口继承 IService 接口并给泛型传入 实体对象名。
-
创建自定义接口的 实现类,并继承 ServiceImpl 实现类。
java
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService{
...
}
实现 接口案例
基于Restful风格实现下列接口:
controller
java
@RequestMapping("/users")
@RestController
@RequiredArgsConstructor //Lombok 自动注入常量
@Api(tags = "用户管理接口")
public class UserController {
private final IUserService userService;
/* private IUserService userService;
public UserController(IUserService userService) { //使用 spring推荐的 构造方法注入
this.userService = userService;
}*/
@ApiOperation("新增用户接口")
@PostMapping
public void saveUser(@RequestBody UserFormDTO userDTO){
// 1. 把DTO 拷贝到PO
User user=BeanUtil.copyProperties(userDTO, User.class); //hutool包 拷贝
userService.save(user);
}
@ApiOperation("删除用户接口")
@DeleteMapping("{id}")
public void saveUser(@ApiParam("用户id") @PathVariable("id")Long id){
// 1. 把DTO 拷贝到PO
userService.removeById(id);
}
@ApiOperation("根据id查询用户接口")
@GetMapping("{id}")
public UserVO queryUserById(@ApiParam("用户id") @PathVariable("id")Long id){
// 1. 查询PO
User user=userService.getById(id);
return BeanUtil.copyProperties(user,UserVO.class);
}
@ApiOperation("根据id查询用户接口")
@GetMapping
public List<UserVO> queryUserById(@ApiParam("用户id集合") @RequestParam("ids")List<Long> ids){
// 1. 查询PO
List<User> users=userService.listByIds(ids);
return BeanUtil.copyToList(users,UserVO.class);
}
// 开发复杂模块
@ApiOperation("扣减用户余额接口")
@PutMapping("/{id}/deduction/{money}")
public void deductMoneyById(
@ApiParam("用户id")@PathVariable("id")Long id,
@ApiParam("扣减的金额")@PathVariable("money") Integer money)
{
userService.deductBalance(id,money);
}
}
service
除了扣减用户余额接口的接口,均可使用 IService 中定义的功能实现。所以在 自定义service 层中不需要实现。
实现扣减余额:
java
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
@Override
public void deductBalance(Long id, Integer money) {
//1.查询用户
User user=this.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
//以多态的方式调用
}
}
Mapper
自定义 Mapper 中实现数据层操作。
java
public interface UserMapper extends BaseMapper<User> {
@Update("update user set balance=balance - #{money} where id=#{id}")
void deductBalance(@Param("id") Long id,@Param("money") Integer money);
}