如果有不懂的或意见建议 欢迎评论!
文章目录 / 点个赞 点个关注吧
1. MybatisPlus 简介
MybatisPlus是基于Mybatis的封装, Mybatis的加强版, 加强了什么呢? 内部使用动态代理 自动生成增删改查操作
如果使用Mybaits 就得需要手动实现 增删改查sql, 效率低还容易出错!
MybaitPlus可以和Mybatis同时使用, 对于复杂sql, 可用继续写xml。且对于调用者来说用法都是统一的!
下面直接看看怎么用
2. 环境配置
在SpringBoot2下使用
-
引入依赖
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.1</version> </dependency>
-
与SpringBoot集成
在application.yml 或 application.properties文件中 加入以下配置
mybatis-plus: # 指定mapper.xml文件地址 mapper-locations: classpath:mapper/*/*Mapper.xml # 指定实体类包 type-aliases-package: cn.wkpower.common.entity configuration: # 自动将下划线模式 转为 驼峰模式 map-underscore-to-camel-case: true
在启动类或其他配置类中加入
import org.mybatis.spring.annotation.MapperScan; // 指定mapper接口的包 @MapperScan("cn.wkpower.common.mapper")
-
orm 字段映射
请先读完这段代码
import lombok.Data; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @Data public class UserFeedback { @TableId(type = IdType.AUTO) private Long id; /** * 反馈用户的id */ private Long userId; /** * 图片 */ private String img; /** * 反馈的内容 */ private String content; @TableField(fill = FieldFill.INSERT) private LocalDateTime gmtCreate; @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime gmtModified; // ================= 补充字段区 =================== @TableField(exist = false) private List<String> imgList; }
是的, 这段代码就完成了ORM数据库映射,Mybaits需要手动写一大串
注解讲解
@TableId 指定主键, 参数type为主键值类型, AUTO代表自增, 具体可直接看源码 com.baomidou.mybatisplus.annotation.IdType
类型 | 含义 | 备注 |
---|---|---|
AUTO | 数据库ID自增 | 需要数据库设置为自增 |
ID_WORKER | 全局唯一ID (idWorker) | 为空时, 框架自动填入 |
UUID | 全局唯一ID (UUID) | 为空时, 框架自动填入 |
ID_WORKER_STR | 字符串全局唯一ID (idWorker 的字符串表示) | 为空时, 框架自动填入 |
@TableField 指定普通映射字段
字段 | 含义 | 备注 |
---|---|---|
value | 数据库中表的字段名 | 可省略, 会自动取Java字段名 |
fill | 字段自动填充策略 | 可选值 INSERT插入时填充字段,UPDATE更新时填充字段,INSERT_UPDATE插入和更新时填充字段, 具体填充什么内容呢?见后续 |
-
继承Mapper接口
泛型为model对象。 BaseMapper这个接口可用点进源码看一看, 定义了很多可用直接用的方法, 在运行时, 这些方法会自动被实现,我们不用管
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import cn.wkpower.common.entity.userinfo.UserFeedback; public interface UserFeedbackMapper extends BaseMapper<UserFeedback> { }
-
控制台打印sql 加入以下配置
/** * sql性能分析插件,输出sql语句及所需时间 */ @Bean public PerformanceInterceptor performanceInterceptor() { return new PerformanceInterceptor(); }
3. 查询操作
3.1 根据id查询数据
@Autowired
private UserFeedbackMapper userFeedbackMapper;
public void testSelectById(){
UserFeedback userFeedback = userFeedbackMapper.selectById(1);
}
3.2 查询全部数据
@Autowired
private UserFeedbackMapper userFeedbackMapper;
public void testSelectList(){
List<UserFeedback> userFeedbacks = userFeedbackMapper.selectList(null);
}
3.3 根据一些条件查询
@Autowired
private UserinfoMapper userinfoMapper;
public void testSelectOne() {
// 查询单个对象 selectOne返回一个对象, selectList返回一个list, 他们的插叙参数都是一样的写法
Userinfo selectOne = userinfoMapper.selectOne(
// 构建查询条件
new QueryWrapper<Userinfo>().lambda()
// age大于等于18 sql为 age >= 18 其他: ge大于等于,gt大于,lt小于,le小于等于
.ge(Userinfo::getAge, 18)
// username的模糊搜索 sql为 %SUN% 其他: rightLike右模糊 leftLike左模糊
.like(Userinfo::getUsername, "SUN")
// sex的精确查询 sql为 sex = 1 其他: ne不等于
.eq(Userinfo::getSex, 1)
// 其他方法可以按提示键自己查看
);
}
3.4 根据对象查询
有时候 我们不想构建查询条件, 太麻烦了, 前端接口直接传来了对象,我们可用直接使用该进行查询, 但是每个查询条件都是精确查询 就是 =
@Autowired
private UserinfoMapper userinfoMapper;
public void testSelectObjs() {
Userinfo userinfo = new Userinfo();
userinfo.setSex(1);
userinfo.setAddress("西安");
// 需强转 sql为 sex = 1 and address = '西安'
List<Object> objects = userinfoMapper.selectObjs(new QueryWrapper<>(userinfo));
}
3.5 自定义sql复杂查询
有时sql实在太长太复杂了, 用Java代码写会不易于维护, 必须得写SQL了, 方式如下
-
在mapper接口定义方法
List<UserRelationTypeResponse> listExistRelation(@Param("deviceType")Integer deviceType, @Param("userId") Long userId);
-
在mapper.xml定义sql
<select id="listExistRelation" resultType="cn.wkpower.common.vo.userinfo.UserRelationTypeResponse"> SELECT user_relation_type FROM <if test="deviceType == 1"> bpinfo </if> <if test="deviceType == 2"> gluinfo </if> GROUP BY userid,user_relation_type HAVING userid = #{userId} UNION /* 一定存在本人的记录 */ SELECT 1 </select>
-
使用方式
@Autowired
private UserinfoMapper userinfoMapper;
public void testCustomSql() {
List<UserRelationTypeResponse> userRelationTypeResponses = userinfoMapper.listExistRelation(1, 1L);
}
发现了没有, 这完全就是Mybatis啊 !
3.6 分页查询
分页功能需新加配置如下
/**
* 分页插件: 配置后就可用使用分页功能了
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
代码
@Autowired
private UserinfoMapper userinfoMapper;
public void testPage() {
// 查询第1页 每页20条数据, 查询条件为空
IPage<Userinfo> userinfoIPage = userinfoMapper.selectPage(new Page<>(1, 20), new QueryWrapper<>());
// 查询第2页 每页20条数据, 查询条件为 id倒叙
IPage<Userinfo> userinfoIPage2 = userinfoMapper.selectPage(new Page<>(2, 20), new QueryWrapper<Userinfo>().lambda().orderByDesc(Userinfo::getUserid));
// 获取返回结果
List<Userinfo> records = userinfoIPage2.getRecords();
// 获取总记录数
long total = userinfoIPage2.getTotal();
}
自定义的sql加入分页功能
-
在mapper接口的改动如下
import com.baomidou.mybatisplus.core.metadata.IPage; /** * 第一个参数 加入分页对象 * 返回参数 使用分页对象进行包装 */ IPage<BindUserListVO> unBindUserList(IPage<BindUserListVO> page, @Param("medicalId") Long medicalId, @Param("identity") Integer identity);
-
对结果的取值与上面的方式一样
// 获取返回结果 List<Userinfo> records = userinfoIPage.getRecords(); // 获取总记录数 long total = userinfoIPage.getTotal();
4. 保存操作 ( 增加 / 更新 )
4.1 插入一条数据
@Autowired
private UserinfoMapper userinfoMapper;
public void testInsert() {
Userinfo userinfo = new Userinfo();
userinfo.setAge(1);
userinfo.setUsername("SUN");
userinfoMapper.insert(userinfo);
}
4.2 插入数据时自动填充创建时间/更新时间
增加填充策略 配置
/**
* 自动赋值配置
*/
@Bean
public MetaObjectHandler metaObjectHandlerConfig(){
return new MetaObjectHandler() {
// 添加时的策略
@Override
public void insertFill(MetaObject metaObject) {
// 设置创建时间为当前时间, gmtCreate为我的字段名 如果你写的是别的填写的
setFieldValByName("gmtCreate", LocalDateTime.now(), metaObject);
// 设置修改时间为当前时间, gmtModified为我的字段名 如果你写的是别的填写的
setFieldValByName("gmtModified", LocalDateTime.now(), metaObject);
}
// 更新时的策略
@Override
public void updateFill(MetaObject metaObject) {
// 将修改时间设置为当前
setFieldValByName("gmtModified", LocalDateTime.now(), metaObject);
}
};
}
model类的更改
// INSERT 会走入 上面配置的insertFill方法
@TableField(fill = FieldFill.INSERT)
private LocalDateTime gmtCreate;
// INSERT_UPDATE 会走入 上面配置的insertFill方法和updateFill方法
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime gmtModified;
使用方式
// 无变化
userInfoMapper.insert(userinfo)
4.3 根据id更新数据
@Autowired
private UserinfoMapper userinfoMapper;
public void testUpdateById() {
Userinfo userinfo = new Userinfo();
userinfo.setAge(1);
userinfo.setUsername("SUN2");
userinfoMapper.updateById(userinfo);
}
4.4 更新部分字段
@Autowired
private UserinfoMapper userinfoMapper;
public void testUpdate() {
Userinfo userinfo = new Userinfo();
userinfo.setAge(1);
userinfo.setUsername("SUN2");
// 写法一: 第一个参数传更新的值 , 第二个参数为查询条件
// 最终的sql为 set age = 1, username = SUN2 WHERE address = "西安"
userinfoMapper.update(userinfo,new QueryWrapper<Userinfo>().lambda().eq(Userinfo::getAddress,"西安"));
// 写法二: 第一个参数不穿, 第二个参数为更新规则
// 最终sql为 set age = 18, username=SUN3 WHERE age = 6
userinfoMapper.update(null,new UpdateWrapper<Userinfo>().lambda().set(Userinfo::getAge,18).set(Userinfo::getUsername,"SUN3").eq(Userinfo::getAge,6));
}
5. 删除操作
5.1 根据id删除数据
@Autowired
private UserinfoMapper userinfoMapper;
public void testDeleteById() {
userinfoMapper.deleteById(1);
}
5.2 根据指定查询规则删除数据
@Autowired
private UserinfoMapper userinfoMapper;
public void testDelete() {
// 构建一个查询条件, 凡是查出来的都会被删除 , 这个写法会删除 age = 18的数据
userinfoMapper.delete(new QueryWrapper<Userinfo>().lambda().eq(Userinfo::getAge,18));
}
5.3 逻辑删除
逻辑删除即不删除真实数据, 而使用一个字段来表示此条记录是否被删除,常见的实现方式为手动维护 比如 select xxx where isdel = 1 / update xx set isdel = 1
但是MybatisPlus已经支持了此功能, 来看看最优雅的写法!
-
首先是Model类的改动
import com.baomidou.mybatisplus.annotation.TableLogic; /** * 是否删除 1是 0否 */ @TableLogic(value = "0", delval = "1") private Integer isdel;
字段上加了@TableLogic 注解 value表示没有被删除的值,delval表示被删除的值
-
删除数据的写法
@Autowired private UserinfoMapper userinfoMapper; public void testDelete() { userinfoMapper.deleteById(1); }
可以看见, 写法没有发生任何改变!
实际上, 在执行以上代码时, 真正的sql将变为
UPDATE userinfo SET isdel = 1 WHERE id = 1
, 删除操作变为了对isdel字段的更新操作还有一个好处是:普通的查询, 例如以下代码 会自动加上 isdel = 0 查出未删除的数据!
userinfoMapper.selectList(null);