mybatis-plus

一、快速入门

1、实现crud

想实现crud,只需要下面几步

1、引入mybatis-plus的依赖

2、定义mapper

引入依赖:

MybatisPlus提供了starter,实现了自动Mybatis以及MybatisPlus的自动装配功能,坐标如下:

<dependency>
    <groupId>***.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.1</version>
</dependency>

我们自定义的Mapper只要实现了这个BaseMapper,就无需自己实现单表CRUD了。

public interface UserMapper extends BaseMapper<User>{
}

2、常见注解

@TableName         @TableId             @TableField

@TableName :是用于表名注解,表示实体类对应的表

@TableId:主键注解,表示实体类的注解

它支持两个属性:

@TableId(value="id",type="IdType.AUTO")

private Long id

IdType支持的类型有:AUTO:数据库主键自增长  INPUT:通过set方法自行输入

ASSIGN_ID:分配 ID(主键类型为 Number(Long 和 Integer)或 String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法)

@TableField:

成员变量名与数据库字段名不一致

成员变量名以isXXX命名,按照JavaBean的规范,MybatisPlus识别字段时会把is去除,这就导致与数据库不符。

成员变量名与数据库名字段名一致,但与数据库关键字冲突

@TableName("user")
public class User {
    @TableId
    private Long id;
    private String name;
    @TableField(exis=false)
    private Integer age;
    @TableField(is_married")
    private Boolean isMarried;
    @TableField("`concat`")
    private String concat;
}

3、总结

MybatisPlus是如何获取实现CRUD的数据库表信息

1、默认以类名驼峰转下划线为表名

2、默认把名为id字段当作主键

3、默认把变量名驼峰转下划线为表字段

MybatisPlus常见注解有

1、@TableName:指定表名称及全局配置

2、@TableId:指定id字段及相关配置

3、@TableField:指定普通字段名称及相关配置

IdType常见类型有:

AUTO、ASSIGN_ID、INPUT

使用@TableField的场景有哪些:

1、成员变量名与数据库字段名不一致

2、成员变量名以is开头,且是布尔值

3、成员变量名与数据库关键字冲突

4、成员变量名不是数据库字段

二、常见配置

MybatisPlus也支持基于yaml文件的自定义配置,详见官方文档:

使用配置 | MyBatis-Plushttps://baomidou.***/reference/

大多数的配置都有默认值,因此我们都无需配置。但还有一些是没有默认值的,例如:

  • 实体类的别名扫描包

  • 全局id类型

三、条件构造器

除了新增以外,修改、删除、查询的SQL语句都需要指定where条件。因此BaseMapper中提供的相关方法除了以id作为where条件以外,还支持更加复杂的where条件。

参数中的Wrapper就是条件构造的抽象类,其下有很多默认实现,继承关系如图:

Wrapper的子类AbstractWrapper提供了where中包含的所有条件构造方法:

而QueryWrapper在AbstractWrapper的基础上拓展了一个select方法,允许指定查询字段:

UpdateWrapper在AbstractWrapper的基础上拓展了一个set方法,允许指定SQL中的SET部分:

1、QueryWrapper

查询:查询出名字中带o的,存款大于等于1000元的人。代码如下:

void testQueryWrapper(){
        //构造条件构造器
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .select("id","username","info","balance")
                .like("username","o")
                .ge("balance",1000);
        //查询数据
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

更新:更新用户名为jack的用户的余额为2000。代码如下:

@Test
    void testUpdateByQueryWrapper(){
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .eq("username","Jack");
        User user = new User();
        user.setBalance(2000);
        userMapper.update(user,wrapper);
    }

2、UpdateWrapper

基于BaseMapper中的update方法更新时只能直接赋值,对于一些复杂的需求就难以实现。

例如:更新id为1,2,4的用户的余额,扣200,对应的SQL应该是:

UPDATE user SET balance = balance - 200 WHERE id in (1, 2, 4)
@Test
    void testUpdateWrapper(){
        List<Long> ids = List.of(1L, 2L, 4L);
        //生成sql
        UpdateWrapper<User> wrapper = new UpdateWrapper<User>()
                .setSql("balance=balance-200")
                .in("id",ids);
        //更新  第一个字段为null,就是不填更新字段与数据
        userMapper.update(null, wrapper);
    }

3、LambdaQueryWrapper

为了解决QueryWrapper、UpdateWrapper的硬编码问题

中一种办法是基于变量的gettter方法结合反射技术。因此我们只要将条件对应的字段的getter方法传递给MybatisPlus,它就能计算出对应的变量名了。而传递方法可以使用JDK8中的方法引用Lambda表达式。 因此MybatisPlus又提供了一套基于Lambda的Wrapper,包含两个:

  • LambdaQueryWrapper

  • LambdaUpdateWrapper

分别对应QueryWrapper和UpdateWrapper

@Test
    void testQueryWrapper(){
        //构造条件构造器
        QueryWrapper<User> wrapper = new QueryWrapper<User>();
                wrapper.lambda()
                .select(User::getId,User::getUsername,User::getInfo,User::getBalance)
                .like(User::getUsername,"o")
                .ge(User::getBalance,1000);
        //查询数据
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

四、自定义SQL

 @Test
    void testUpdateWrapper(){
        List<Long> ids = List.of(1L, 2L, 4L);
        //生成sql
        UpdateWrapper<User> wrapper = new UpdateWrapper<User>();
                wrapper.lambda()
                .setSql("balance=balance-200")
                .in(User::getId,ids);
        //更新  第一个字段为null,就是不填更新字段与数据
        userMapper.update(null, wrapper);
    }

这种写法在某些公司是不允许的,因为SQL语句最好都维护在持久层,而不是业务层。

五、Service接口

MybatisPlus不仅提供了BaseMapper,还提供了通用的Service接口及默认实现,封装了一些常用的service模板方法。

通用接口为IService,默认实现为ServiceImpl,其中封装的方法可以分为以下几类

  • save:新增

  • remove:删除

  • update:更新

  • get:查询单个结果

  • list:查询集合结果

  • count:计数

  • page:分页查询

1、CRUD

新增:

1、save 是新增单个元素

2、saveBatch 是批量新增

3、savaOrUpdate 是根据id判断,如果数据存在就是更新,否则就是新增

4、saveOrUpdateBatch 是批量的新增或修改

删除:

1、removeById:根据id删除

2、removeByIds:根据ids批量删除

3、removeByMap:根据Map中的键值对为条件删除

4、remove(Wrapper<T>):根据Wrapper条件删除

修改:

1、updateById:根据id修改

2、update(Wrapper<T>):根据UpdateWrapper修改,Wrapper中包含set和where部分

3、update(T,Wrapper<T>):按照T内的数据修改与Wrapper匹配到的数据

4、updateBatchById:根据id批量修改

List:

1、listByIds:根据id批量查询

2、list(Wrapper<T>):根据Wrapper条件查询多条数据

3、list():查询所有

Count:

1、count():统计所有数量

2、count(Wrapper<T>):统计符合Wrapper条件的数据数量

总结:

2、用法

对于简单的增删改查,我们可以之间在controller里调mp里面提供的service方法,无需写任何自定义service或mapper。

只有在我们这个业务逻辑相对复杂,需要自己写一些业务,而mp只能提供简单的增删改查,我们才需要自己写service和mapper

3、Lambda

IService中还提供了Lambda功能来简化我们的复杂查询及更新功能。我们用两个案例来学一下

@GetMapping("/list")
@ApiOperation("根据id集合查询用户")
public List<UserVO> queryUsers(UserQuery query){
    // 1.组织条件
    String username = query.getName();
    Integer status = query.getStatus();
    Integer minBalance = query.getMinBalance();
    Integer maxBalance = query.getMaxBalance();
    LambdaQueryWrapper<User> wrapper = new QueryWrapper<User>().lambda()
            .like(username != null, User::getUsername, username)
            .eq(status != null, User::getStatus, status)
            .ge(minBalance != null, User::getBalance, minBalance)
            .le(maxBalance != null, User::getBalance, maxBalance);
    // 2.查询用户
    List<User> users = userService.list(wrapper);
    // 3.处理vo
    return BeanUtil.copyToList(users, UserVO.class);
}

在组织查询条件的时候,我们加入了 username != null 这样的参数,意思就是当条件成立时才会添加这个查询条件,类似Mybatis的mapper.xml文件中的<if>标签。这样就实现了动态查询条件效果了。

不过,上述条件构建的代码太麻烦了。 因此Service中对LambdaQueryWrapperLambdaUpdateWrapper的用法进一步做了简化。我们无需自己通过new的方式来创建Wrapper,而是直接调用lambdaQuerylambdaUpdate方法:

@GetMapping("/list")
@ApiOperation("根据id集合查询用户")
public List<UserVO> queryUsers(UserQuery query){
    // 1.组织条件
    String username = query.getName();
    Integer status = query.getStatus();
    Integer minBalance = query.getMinBalance();
    Integer maxBalance = query.getMaxBalance();
    // 2.查询用户
    List<User> users = userService.lambdaQuery()
            .like(username != null, User::getUsername, username)
            .eq(status != null, User::getStatus, status)
            .ge(minBalance != null, User::getBalance, minBalance)
            .le(maxBalance != null, User::getBalance, maxBalance)
            .list();
    // 3.处理vo
    return BeanUtil.copyToList(users, UserVO.class);
}

可以发现lambdaQuery方法中除了可以构建条件,还需要在链式编程的最后添加一个list(),这是在告诉MP我们的调用结果需要是一个list集合。这里不仅可以用list(),可选的方法有:

  • .one():最多1个结果

  • .list():返回集合结果

  • .count():返回计数结果

@GetMapping("/list")
@ApiOperation("根据id集合查询用户")
public List<UserVO> queryUsers(UserQuery query){
    // 1.组织条件
    String username = query.getName();
    Integer status = query.getStatus();
    Integer minBalance = query.getMinBalance();
    Integer maxBalance = query.getMaxBalance();
    LambdaQueryWrapper<User> wrapper = new QueryWrapper<User>().lambda()
            .like(username != null, User::getUsername, username)
            .eq(status != null, User::getStatus, status)
            .ge(minBalance != null, User::getBalance, minBalance)
            .le(maxBalance != null, User::getBalance, maxBalance);
    // 2.查询用户
    List<User> users = userService.list(wrapper);
    // 3.处理vo
    return BeanUtil.copyToList(users, UserVO.class);
}

进一步简化

@GetMapping("/list")
@ApiOperation("根据id集合查询用户")
public List<UserVO> queryUsers(UserQuery query){
    // 1.组织条件
    String username = query.getName();
    Integer status = query.getStatus();
    Integer minBalance = query.getMinBalance();
    Integer maxBalance = query.getMaxBalance();
    // 2.查询用户
    List<User> users = userService.lambdaQuery()
            .like(username != null, User::getUsername, username)
            .eq(status != null, User::getStatus, status)
            .ge(minBalance != null, User::getBalance, minBalance)
            .le(maxBalance != null, User::getBalance, maxBalance)
            .list();
    // 3.处理vo
    return BeanUtil.copyToList(users, UserVO.class);
}

4、IService批量新增

转载请说明出处内容投诉
CSS教程网 » mybatis-plus

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买