MyBatis-plus

核心功能

注解

mp一共提供了8个注解,这些注解是用在Java的实体类上面的。

@TableName

注解在类上,指定类和数据库表的映射关系。实体类的类名(转成小写后)和数据库表名相同时,可以不指定该注解。

@TableField

注解在某一字段上,指定Java实体类的字段和数据库表的列的映射关系。这个注解有如下几个应用场景。

  • 排除非表字段

    若Java实体类中某个字段,不对应表中的任何列,它只是用于保存一些额外的,或组装后的数据,则可以设置exist属性为false,这样在对实体对象进行插入时,会忽略这个字段。排除非表字段也可以通过其他方式完成,如使用statictransient关键字

  • 字段验证策略

    通过insertStrategyupdateStrategywhereStrategy属性进行配置,可以控制在实体对象进行插入,更新,或作为WHERE条件时,对象中的字段要如何组装到SQL语句中

  • 字段填充策略

    通过fill属性指定,字段为空时会进行自动填充

  • @Version

    乐观锁注解

    @EnumValue

    注解在枚举字段上

    @TableLogic

    逻辑删除

    KeySequence

    序列主键策略(oracle

    InterceptorIgnore

    插件过滤规则

 

Mapper CRUD接口

只需定义好实体类,然后创建一个接口,继承mp提供的BaseMapper,即可食用。mp会在mybatis启动时,自动解析实体类和表的映射关系,并注入带有通用CRUD方法的mapper。BaseMapper里提供的方法,部分列举如下:

  • insert(T entity)  插入一条记录

  • deleteById(Serializable id)  根据主键id删除一条记录

  • delete(Wrapper<T> wrapper) 根据条件构造器wrapper进行删除

  • selectById(Serializable id) 根据主键id进行查找

  • selectBatchIds(Collection idList) 根据主键id进行批量查找

  • selectByMap(Map<String,Object> map) 根据map中指定的列名和列值进行等值匹配查找

  • selectMaps(Wrapper<T> wrapper)  根据 wrapper 条件,查询记录,将查询结果封装为一个Map,Map的key为结果的列,value为值

  • @Test  
       public void test3() {  
        QueryWrapper<User> wrapper = new QueryWrapper<>();  
        wrapper.select("id","name","email").likeRight("name","黄");  
        List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);  
        maps.forEach(System.out::println);  
       }
  • selectList(Wrapper<T> wrapper) 根据条件构造器wrapper进行查询

  • update(T entity, Wrapper<T> wrapper) 根据条件构造器wrapper进行更新

  • updateById(T entity)

  • selectObjs

    只会返回第一个字段(第一列)的值,其他字段会被舍弃

    比如

    @Test  
     public void test3() {  
      QueryWrapper<User> wrapper = new QueryWrapper<>();  
      wrapper.select("id""name").like("name""黄");  
      List<Object> objects = userMapper.selectObjs(wrapper);  
      objects.forEach(System.out::println);  
     }

 

selectObjs

 

只会返回第一个字段(第一列)的值,其他字段会被舍弃

 

比如

 

@Test  
 public void test3() {  
  QueryWrapper<User> wrapper = new QueryWrapper<>();  
  wrapper.select("id""name").like("name""黄");  
  List<Object> objects = userMapper.selectObjs(wrapper);  
  objects.forEach(System.out::println);  
 }

selectCount

查询满足条件的总数,注意,使用这个方法,不能调用QueryWrapperselect方法设置要查询的列了。这个方法会自动添加select count(1)

比如

@Test  
 public void test3() {  
  QueryWrapper<User> wrapper = new QueryWrapper<>();  
  wrapper.like("name""黄");  
  
  Integer count = userMapper.selectCount(wrapper);  
  System.out.println(count);  
 }

Service CRUD 接口

另外一套CRUD是Service层的,只需要编写一个接口,继承IService,并创建一个接口实现类,比较明显的区别在于IService支持了更多的批量化操作,如saveBatchsaveOrUpdateBatch等方法。

1.首先,新建一个接口,继承IService

package com.example.mp.service;  
     
   import com.baomidou.mybatisplus.extension.service.IService;  
   import com.example.mp.po.User;  
     
   public interface UserService extends IService<User> {  
   }

2.创建这个接口的实现类,并继承ServiceImpl,最后打上@Service注解,注册到Spring容器中,即可食用

package com.example.mp.service.impl;  
     
   import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;  
   import com.example.mp.mappers.UserMapper;  
   import com.example.mp.po.User;  
   import com.example.mp.service.UserService;  
   import org.springframework.stereotype.Service;  
     
   @Service  
   public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

3.测试代码

package com.example.mp;  
     
   import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;  
   import com.baomidou.mybatisplus.core.toolkit.Wrappers;  
   import com.example.mp.po.User;  
   import com.example.mp.service.UserService;  
   import org.junit.Test;  
   import org.junit.runner.RunWith;  
   import org.springframework.beans.factory.annotation.Autowired;  
   import org.springframework.boot.test.context.SpringBootTest;  
   import org.springframework.test.context.junit4.SpringRunner;  
   @RunWith(SpringRunner.class)  
   @SpringBootTest  
   public class ServiceTest {  
    @Autowired  
    private UserService userService;  
    @Test  
    public void testGetOne() {  
     LambdaQueryWrapper<User> wrapper = Wrappers.<User>lambdaQuery();  
     wrapper.gt(User::getAge, 28);  
     User one = userService.getOne(wrapper, false); // 第二参数指定为false,使得在查到了多行记录时,不抛出异常,而返回第一条记录  
     System.out.println(one);  
    }  
   }

IService也支持链式调用
IService
@Test  
 public void testChain() {  
  List<User> list = userService.lambdaQuery()  
    .gt(User::getAge, 39)  
    .likeRight(User::getName, "王")  
    .list();  
  list.forEach(System.out::println);  
 }

更新示例如下

@Test  
 public void testChain() {  
  userService.lambdaUpdate()  
    .gt(User::getAge, 39)  
    .likeRight(User::getName, "王")  
    .set(User::getEmail, "w39@baomidou.com")  
    .update();  
 }

删除示例如下

@Test  
 public void testChain() {  
  userService.lambdaUpdate()  
    .like(User::getName, "青蛙")  
    .remove();  
 }


条件构造器

mp让我觉得极其方便的一点在于其提供了强大的条件构造器Wrapper,可以非常方便的构造WHERE条件。条件构造器主要涉及到3个类,AbstractWrapperQueryWrapperUpdateWrapper,它们的类关系如下

 

 

在AbstractWrapper中提供了非常多的方法用于构建WHERE条件,而QueryWrapper针对SELECT语句,提供了select()方法,可自定义需要查询的列,而UpdateWrapper针对UPDATE语句,提供了set()方法,用于构造set语句
AbstractWrapper
QueryWrapper
SELECT
select()
UpdateWrapper
UPDATE
set()
set

AbstractWrapper中用于构建SQL语句中的WHERE条件的方法进行部分列举

  • eq:equals,等于
  • allEq:all equals,全等于
  • ne:not equals,不等于
  • gt:greater than ,大于 >
  • ge:greater than or equals,大于等于
  • lt:less than,小于<
  • le:less than or equals,小于等于
  • between:相当于SQL中的BETWEEN
  • notBetween
  • like:模糊匹配。like("name","黄"),相当于SQL的name like '%黄%'
  • likeRight:模糊匹配右半边。likeRight("name","黄"),相当于SQL的name like '黄%'
  • likeLeft:模糊匹配左半边。likeLeft("name","黄"),相当于SQL的name like '%黄'
  • notLikenotLike("name","黄"),相当于SQL的name not like '%黄%'
  • isNull
  • isNotNull
  • in
  • and:SQL连接符AND
  • or:SQL连接符OR
  • apply:用于拼接SQL,该方法可用于数据库函数,并可以动态传参

 

 

// 案例先展示需要完成的SQL语句,后展示Wrapper的写法  
  
// 1. 名字中包含佳,且年龄小于25  
// SELECT * FROM user WHERE name like '%佳%' AND age < 25  
QueryWrapper<User> wrapper = new QueryWrapper<>();  
wrapper.like("name", "佳").lt("age", 25);  
List<User> users = userMapper.selectList(wrapper);  
// 下面展示SQL时,仅展示WHERE条件;展示代码时, 仅展示Wrapper构建部分  
  
// 2. 姓名为黄姓,且年龄大于等于20,小于等于40,且email字段不为空  
// name like '黄%' AND age BETWEEN 20 AND 40 AND email is not null  
wrapper.likeRight("name","黄").between("age", 20, 40).isNotNull("email");  
  
// 3. 姓名为黄姓,或者年龄大于等于40,按照年龄降序排列,年龄相同则按照id升序排列  
// name like '黄%' OR age >= 40 order by age desc, id asc  
wrapper.likeRight("name","黄").or().ge("age",40).orderByDesc("age").orderByAsc("id");  
  
// 4.创建日期为2021年3月22日,并且直属上级的名字为李姓  
// date_format(create_time,'%Y-%m-%d') = '2021-03-22' AND manager_id IN (SELECT id FROM user WHERE name like '李%')  
wrapper.apply("date_format(create_time, '%Y-%m-%d') = {0}", "2021-03-22") // 建议采用{index}这种方式动态传参, 可防止SQL注入  
    .inSql("manager_id", "SELECT id FROM user WHERE name like '李%'");  
// 上面的apply, 也可以直接使用下面这种方式做字符串拼接,但当这个日期是一个外部参数时,这种方式有SQL注入的风险  
wrapper.apply("date_format(create_time, '%Y-%m-%d') = '2021-03-22'");  

  
// 5. 名字为王姓,并且(年龄小于40,或者邮箱不为空)  
// name like '王%' AND (age < 40 OR email is not null)  
wrapper.likeRight("name", "王").and(q -> q.lt("age", 40).or().isNotNull("email"));  
  
// 6. 名字为王姓,或者(年龄小于40并且年龄大于20并且邮箱不为空)  
// name like '王%' OR (age < 40 AND age > 20 AND email is not null)  
wrapper.likeRight("name", "王").or(  
    q -> q.lt("age",40)  
      .gt("age",20)  
      .isNotNull("email")  
  );  
  
// 7. (年龄小于40或者邮箱不为空) 并且名字为王姓  
// (age < 40 OR email is not null) AND name like '王%'  
wrapper.nested(q -> q.lt("age", 40).or().isNotNull("email"))  
    .likeRight("name", "王");  
  
// 8. 年龄为30,31,34,35  
// age IN (30,31,34,35)  
wrapper.in("age", Arrays.asList(30,31,34,35));  
// 或  
wrapper.inSql("age","30,31,34,35");  
  
// 9. 年龄为30,31,34,35, 返回满足条件的第一条记录  
// age IN (30,31,34,35) LIMIT 1  
wrapper.in("age", Arrays.asList(30,31,34,35)).last("LIMIT 1");  
  
// 10. 只选出id, name 列 (QueryWrapper 特有)  
// SELECT id, name FROM user;  
wrapper.select("id", "name");  
  
// 11. 选出id, name, age, email, 等同于排除 manager_id 和 create_time  
// 当列特别多, 而只需要排除个别列时, 采用上面的方式可能需要写很多个列, 可以采用重载的select方法,指定需要排除的列  
wrapper.select(User.class, info -> {  
   String columnName = info.getColumn();  
   return !"create_time".equals(columnName) && !"manager_id".equals(columnName);  
  });

 
===============================================》

更新操作

上面介绍的都是查询操作,现在来讲更新和删除操作。

BaseMapper中提供了2个更新方法

  • updateById(T entity)

根据入参entityid(主键)进行更新,对于entity中非空的属性,会出现在UPDATE语句的SET后面,即entity中非空的属性,会被更新到数据库,示例如下

@RunWith(SpringRunner.class)  
  @SpringBootTest  
  public class UpdateTest {  
   @Autowired  
   private UserMapper userMapper;  
   @Test  
   public void testUpdate() {  
    User user = new User();  
    user.setId(2L);  
    user.setAge(18);  
    userMapper.updateById(user);  
   }  
  }



 

 

 
 
 
 

 

posted @   KLAPT  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示