前言
距离上一篇文章已经过去一个多礼拜了!年后第一周就各种加班,忙成狗,今天分享的是MP入门使用教程的中篇部分!
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。有了它我们不再需要写多余的配置文件或者方法。上一篇文章SpringBoot系列:MybatisPlus的入门级使用教程(上)简单介绍了MyBatis-Plus以及它的一些基础的CRUD,今天这篇文章继续学习MyBatis-Plus。
正文
本文是在上一篇文章的基础之上进行拓展,所以如果有不清楚的可以先参考上一篇文章SpringBoot系列:MybatisPlus的入门级使用教程(上),源码地址会放在最后。
MyBatis-Plus给我们提供了自动填充的功能。一般时候如果我们更新或者插入数据的时候有更新时间或者创建时间,我们可以通过给这两个字段赋值的形式进行更新。比如:
user.setCreateTime("2022-02-12"); user.setUpdateTime("2022-02-12"); 复制代码
但是如果使用MyBatis-Plus则不需要这样操作。使用MyBatis-Plus只需要在实体类上添加@TableField注解,然后赋值类型。该注解用于标识非主键的字段,将数据库列与 JavaBean 中的属性进行映射。其源码如下:
@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface TableField { String value() default ""; String el() default ""; boolean exist() default true; String condition() default ""; String update() default ""; FieldStrategy strategy() default FieldStrategy.DEFAULT; FieldFill fill() default FieldFill.DEFAULT; boolean select() default true; } 复制代码
其中有个FieldFill 属性,表示字段填充策略,FieldFill是个枚举类,列举了具体的字段填充策略源码如下:
public enum FieldFill { DEFAULT, //默认不处理 INSERT, //插入填充字段 UPDATE, //更新填充字段 INSERT_UPDATE; //插入和更新填充字段 private FieldFill() { } } 复制代码
所以在实体类的的对应字段上可以这样使用:
//create_time @TableField(fill = FieldFill.INSERT) private Date createTime; //update_time @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; 复制代码
做到这里还不足以实现自动填充,还需要做个一个元数据的处理策略,声明一个自动填充处理类:
@Component public class MyMetaObjectHandler implements MetaObjectHandler { //使用mp的添加操作,则执行这个方法 @Override public void insertFill(MetaObject metaObject) { this.setFieldValByName("createTime",new Date(),metaObject); this.setFieldValByName("updateTime",new Date(),metaObject); } //使用mp的更新操作,则这个方法执行 @Override public void updateFill(MetaObject metaObject) { this.setFieldValByName("updateTime",new Date(),metaObject); } } 复制代码
测试方法:
//测试插入数据自动填充 @Test public void insertUser1(){ User user = new User(); user.setName("艾希2"); user.setAge(33); user.setEmail("hanbing2@lol.com"); int insertCount = userMapper.insert(user); System.out.println("插入数据的条数是:"+insertCount); } //更新 @Test public void updateUser(){ User user = new User(); user.setId(1l); user.setAge(99); int updateCount = userMapper.updateById(user); System.out.println(updateCount); } 复制代码
结果在更新的时候,更新了update_time字段,插入的时候同时更新了create_time和update_time字段:
MP提供了丰富的查询接口处理,比如如果需要根据一个id查询数据,可以使用:
@Test public void testSelectById(){ User user = userMapper.selectById(1L); System.out.println(user); } 复制代码
如果需要通过多个id批量查询,可以这样写:
@Test public void testSelectBatchIds(){ List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3)); users.forEach(System.out::println); } 复制代码
还可以通过一个map对象封装查询条件:
//根据条件查询 @Test public void selectuserbymap(){ HashMap<String,Object> map = new HashMap<>(); map.put("age",26); map.put("email","liqing@lolo.com"); List<User> users = userMapper.selectByMap(map); System.out.println(users); } 复制代码
这里map中的key对应的是数据库中的列名。例如数据库user_id,实体类是userId,这时map的key需要填写user_id。
查询所有数据,则可以这样写:
@Test public void findAll(){ List<User> users = userMapper.selectList(null); System.out.println(users); } 复制代码
可以发现这里的selectlist方法后面的参数传了一个null,这是因为MP提供了封装查询条件的条件构造器queryWrapper,通过该类进行条件封装,然后将该封装的对象传入查询的方法中,MP会自动进行条件处理,如参数为null,则没有条件。这里也是MP内容比较多的部分,将放在下一篇中。
MP提供删除的方法和查询很像,可以通过简单的id查询,多个id查询以及条件组合查询,比如:
//根据id删除操作 @Test public void deletebyid(){ int result = userMapper.deleteById(1489438016182263810l); System.out.println(result); } //根据id批量删除操作 @Test public void deletebybatchid(){ int result = userMapper.deleteBatchIds(Arrays.asList(1489160121316552706l,1488850305184493570l)); System.out.println(result); } //按照条件删除 @Test public void deletebymap(){ HashMap<String,Object> map = new HashMap<>(); map.put("age",44); map.put("email","gailun@lolo.com"); int result = userMapper.deleteByMap(map); System.out.println(result); } 复制代码
以上的这些删除都是物理删除即将对应数据从数据库中删除,之后查询不到此条被删除数据,是真实的删除。
MP还提供了逻辑删除的方法。这是通过在数据库中新增一个字段表示是否是逻辑删除,比如deleted字段。然后在实体类中加入@TableLogic注解
//逻辑删除 @TableLogic @TableField(fill = FieldFill.INSERT) private Integer deleted 复制代码
@TableLogic注解表示逻辑删除,源码如下:
@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface TableLogic { String value() default ""; String delval() default ""; } 复制代码
注解参数:value = 未删除的值,默认值为0
delval = 删除后的值,默认值为1
可以跟上述代码中一样使用,也可以这样使用
@TableLogic(value=“原值”,delval=“修改值”) 复制代码
也可以application.properties 加入配置,设置默认值,如果默认值和mp默认的一样,则可以省略:
#mp逻辑删除相关配置 mybatis-plus.global-config.db-config.logic-delete-value=1; mybatis-plus.global-config.db-config.logic-not-delete-value=0; 复制代码
还可以在元对象处理器接口添加deleted的insert默认值,则插入默认更新该字段默认值。
this.setFieldValByName("deleted", 0, metaObject); 复制代码
最后这里需要使用注入ISqlInjector组件,该组件内返回的是LogicSqlInjector。
@Bean public ISqlInjector sqlInjector() { return new LogicSqlInjector(); } 复制代码
LogicSqlInjector源码如下:
public class LogicSqlInjector extends AbstractSqlInjector { public LogicSqlInjector() { } public List<AbstractMethod> getMethodList() { return (List)Stream.of(new Insert(), new LogicDelete(), new LogicDeleteByMap(), new LogicDeleteById(), new LogicDeleteBatchByIds(), new LogicUpdate(), new LogicUpdateById(), new LogicSelectById(), new LogicSelectBatchByIds(), new LogicSelectByMap(), new LogicSelectOne(), new LogicSelectCount(), new LogicSelectMaps(), new LogicSelectMapsPage(), new LogicSelectObjs(), new LogicSelectList(), new LogicSelectPage()).collect(Collectors.toList()); } } 复制代码
提供了很多逻辑删除(LogicDelete)的方法。测试逻辑删除:
//测试 逻辑删除:先插入一条数据,自动填充deleted为0,删除后字段变成1,执行findall方法会排除delete等于1的数据 @Test public void testLogicDelete() { int result = userMapper.deleteById(2l); System.out.println(result); } 复制代码
id为2的之前deleted字段的值为0,现在更改了为1。则表示逻辑删除成功。逻辑删除之后,数据库中仍然保留了该条数据,但是默认查询不到该条数据了。因为查询语句后面默认是加了条件 WHERE deleted=0。
总结
以上就是关于mybatisplus的一些简单的介绍以及关于查找和插入的简单使用,篇幅有限后续将继续更新。更多关于mybatisplus的内容可以参考以下内容:
mybatisplus源码地址: https://gitcode.net/mirrors/baomidou/mybatis-plus?utm_source=csdn_github_accelerator MP官网地址: https://baomidou.com/pages/24112f/ 复制代码