mp使用的基本流程
1、引入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
2、定义Mapper
public interface UserMapper extends BaseMapper<User>{
//指定泛型
}
3、在实体类上添加注解声明表信息
4、在application.yml中根据需要添加配置
常见注解
MybatisPlus通过扫描实体类并基于反射获取实体类信息作为数据库表信息。
约定大于配置:
- 类名驼峰转下划线作为表名
- 名为id的字段作为主键
- 变量名驼峰转下划线作为表的字段名
如果实体类不符合约定,需要自己去定义表名、主键名、字段名
@TableName
@TableId (value=“id”,type=IdType.AUTO )
idType枚举
- AUTO 数据库自增长
- INPUT 通过set方法自行输入
- ASSIGN_ID:分配ID,生成一个长度为20的long型的整数(雪花算法)
@TableFiled
使用@TableFiled的场景
- 成员变量与数据库字段名不一致
- 成员变量名以is开头,且是布尔值
@TableFiled(“is_married”)
private Boolean isMarried;//mp通过反射机制获取名称,会把is去掉,得到变量名Married,就没办法驼峰转下划线了,所以需要用value属性指定数据库字段
- 成员变量与数据库关键字冲突
//数据库字段出现了关键字,可以用转义字符来处理
@TableFiled("'order'")
private Integer order;
- 成员变量不是数据库字段
//如果不去处理,会被当成数据库字段,产生的SQL语句有它会报错
@TableFiled(exist = false)
private String address;
总结:
mp是如何获取实现CRUD的数据库表信息的?
- 类名驼峰转下划线作为表名
- 名为id的字段作为主键
- 变量名驼峰转下划线作为表的字段名
mp常用注解
- @TableName
- @TableId (idType 常见类型:AUTO、ASSING_ID、INPUT)
- @TableFiled
- 与数据库字段不一致、以is开头且是布尔值、与数据库关键字冲突、不是数据库字段
常用配置
mybatis-plus:
type-aliases-package: com.itheima.mp.domain # 别名扫描包
mapper-locations: "classpath:/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 #更新策略:只更新非空字段
除了第一行扫描包,其他不用配置,不写是默认的
核心功能(复杂一些的CURD)
条件构造器
例如:delete(Wrapper<T>):int
在 QueryWrapper 的源码中看到,这个类继承了一个 AbstractWrapper ,这个类主要的作用是生成了 SQL 中的 WHERE 条件,封装了查询的条件。
eq等于 ne不等于 gt大于 ge大于等于 lt 小于 like模糊
场景:查询账户余额大于等于1000,然后模糊查询名字里含有o
的,并只查出id、username、info。
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
.select(User::getId, User::getUsername,User::getInfo)
.like(User::getUsername,"o")
.ge(User::getBalance , 1000);
@Test
public void demo1(){
//1、构建查询条件,支持链式编程
QueryWrapper<User> wrapper = new QueryWrapper<User>()
.select("id","username","info","balance")
.ge("balance",1000)
.like("username","o");
List<User> users = userMapper.selectList(wrapper);
// users.forEach(user -> System.out.println(user));
users.forEach(System.out:: println);
}
尽量使用LambdaQueryWrapper和LambdaUpdateWrapper尽量避免硬编码。
自定义SQL
利用mp的wrapper来构建复杂的where,然后自定义SQL语句中剩下的部分。
解决的问题:不用mp很麻烦,但是用了需要拼接SQL违背企业开发规范
public interface UserMapper extends BaseMapper<User> {
int updateBalanceByIds(List<Long> ids, int amount);
}
<mapper namespace="com.itheima.mp.mapper.UserMapper">
<update id="updateBalanceByIds">
update user
set balance = balance - #{amonut}
where id in
<foreach collection="ids" separator="," item="id" open="(" close=")">
#{id}
</foreach>
</update>
</mapper>
List<Long> ids = new ArrayList<Long>();
Collections.addAll(ids,1L,2L,3L);
UpdateWrapper<User> wrapper = new UpdateWrapper<User>()
.setSql("balance = balance - 200")
.in("id",ids);
//200是个具体值,但开发中应该是个动态值多一些
userMapper.update(null, wrapper);
因此mp只负责where条件的构建,剩下mp不擅长需要我们自己自定义。
- 基于wrapper构建where条件(在业务层用wrapper创建条件,再用mapper传进去)
List<Long> ids = new ArrayList<Long>();
int amount = 200;
//1、构建条件
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>().in(User::getId,ids);
//2、自定义SQL方法调用
userMapper.updateBalanceByIds(wrapper,amount);
- 在mapper方法参数中用Param注解声明wrapper变量名称,必须是ew
void updateBalanceByIds(@Param("ew")LambdaQueryWrapper<User> wrapper, @Param("amount") int amount);
- 自定义SQL,并使用wrapper条件
<update id="updateBalanceByIds2">
update user set balance = balance - #{amount} ${ew.customSqlSegment}
</update>
即实现了不在业务层编写SQL,同时又享受到了mp的生成SQL的方便
**总结:**何时需要自定义?SQL语句where条件之外的部分难以以mp更方便的实现