MybatisPuls

1.介绍你对MybatisPlus的理解?

mybatisPuls是对Mybatis的一个增强,在Mybatis的基础上进行增强,内部提供好了对于单表的简单的crud操作,可以提高效率,简称:MP

MP的特性:

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑

  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作

  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求

  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错

  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题

  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作

  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )

  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用

  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询

  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库

  • 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询

  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

 需要引入的依赖为:
      

普通Maven项目下的依赖
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus</artifactId>
    <version>3.4.2</version>
</dependency>
SpringBoot环境下的MP启动器(导入这个启动器后不需要再导入Mybatis的启动器)
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.1</version>
</dependency>

配置文件配置数据库连接时可以加上sql打印:
   #mybatis-plus配置控制台打印完整带参数SQL语句
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 

MybatisPlus和Mybatis是什么关系?

       MybatisPlus是增强版的Mybatis,对Mybatis只做增强,不影响其原有的功能

MybatisPlus可以解决那些问题?

      当需要对单表进行简单的crud时,需要写sql什么的,太过于麻烦,这时候可以用mybatisPlus进行操作,只需要调用api传入相关的参数即可。

MybatisPlus使用步骤?

       1:导入依赖      2:配置链接数据库    3:就可以使用了    4:想要使用分页查询需要使用分页内部拦截器      5:可以使用逆向工程生成service    impl    mapper   pojo层

     第一步的依赖上边已经写过了

     第四步的配置拦截器代码:
     

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybatisPlusConfig {

    /**
     * 想要使用分页,那么就要配置分页拦截器
     *
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        //第一步想创建一个mybatisPlus拦截器对象
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        //创建一个分页内部拦截器,类型是musql
        PaginationInnerInterceptor interceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        //设置页面最大效果,默认是false,  true:如果请求的页数是10,但是一共就9页,那么就返回第一页也就是首页的值    false:如果查询的10一共9页,那么就继续查询第十页,明显是空
        interceptor.setOverflow(true);
        //设置最大单页限制数量,-1不受限制
        interceptor.setMaxLimit(-1L);
        mybatisPlusInterceptor.addInnerInterceptor(interceptor);
        return mybatisPlusInterceptor;
    }

MybatisPlus封装Service层的步骤

     第一步,service实现Iservice("数据库对应的实体类")     第二步:因为service层实现了Iservice,所以service的实现层也就是impl里面,也要实现Iservice,所以impl的实现类也要继承ServiceImpl这个类,因为ServiceImpl实现了IService然后再去实现service层
       

MybatisPlus-API方法介绍

       具体实现和细节看代码:
      测试类都是api:
      

package com.itheima;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.mapper.UserMapper;
import com.itheima.pojo.User;
import com.itheima.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.*;

@SpringBootTest
public class TestMybatiesRuMen {
    @Autowired
    private UserMapper userMapper;


    @Autowired
    private UserService userService;

    @Test
    public void testFindById() {

        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("user_name", "赵一伤");
        List<User> users = userMapper.selectList(userQueryWrapper);
        System.out.println(users);
//        User user = userMapper.selectById(1);
//        System.out.println("user = " + user);
    }

    @Test
    public void insert01() {
        /**
         * 没有指定添加的id,mybatiesplus底层自动生成一个雪花算法来填充主键
         * 如果传入到insert中的实体类写入了主键的值,那么就讲填入的主键的值插入进去
         */
        User build = User.builder()
                .userName("hmhinsert01")
                .name("hmhname")
                .age(18)
                .email("1374729938@qq.com1")
                .password("1234567").build();
        int insert = userMapper.insert(build);
        if (insert > 0) {
            System.out.println("添加成功");
        }
    }

    /**
     * 根据id批量删除
     */
    @Test
    public void testDelete() {
        //创建集合将需要删除的id保存进去然后之间将这个集合给mybatisplus的方法就可完成删除这个集合中的所有的id
        ArrayList<Long> longs = new ArrayList<>();
        longs.add(1537667301311516673L);
        longs.add(1537667301311516674L);
        int i = userMapper.deleteBatchIds(longs);
        if (i > 1) System.out.println("删除成功");
    }


    @Test
    public void testDelete02() {
        int delete = userMapper.deleteById(1537667301311516675L);
        if (delete > 1) System.out.println("删除成功");
    }

    /**
     * 根据map删除
     * key在使用特殊符号的时候,尽量小心点,一下面为例子,--  就会出现sql错误因为最后弄出来以后是这样的一条sql
     * DELETE FROM tb_user WHERE -- user_name = ? AND id = ? AND email = ?
     * 会发现where后面的被-- 注释了
     */
    @Test
    public void deleteByMap() {
        Map<String, Object> map = new HashMap<>();
        map.put("-- user_name", "hmhinsert01");
        map.put("id", "1537664068602064898");
        map.put("email", "赵七伤");
        int i = userMapper.deleteByMap(map);
        if (i > 0) {
            System.out.println("map删除成功");
        }
    }

    /**
     * 修改   修改的时候必须填写被修改的值的id
     */
    @Test
    public void testUpdate() {
        // 构建修改后的数据信息
        User user = User.builder()
                .id(2L)
                .userName("liuyan")
                .password("6669")
                .name("柳岩")
                .age(18)
                .email("liuyan@qq.com")
                .build();
        int i = userMapper.updateById(user);
        System.out.println(i > 0 ? "修改成功" : "修改失败");
    }

    /**
     * 分页查询
     * 在mybatisPlus中分页查询需要配置分页拦截器
     */
    @Test
    public void testPage01() {
        Page<User> page = new Page<>(1, 2);
        page.setMaxLimit(-1L);
        //下边是设置排序,可以插入集合,具体用法如下
        List<OrderItem> orders = new ArrayList<>();
        orders.add(OrderItem.asc("age"));
        orders.add(OrderItem.asc("id"));
        page.setOrders(orders);
        userMapper.selectPage(page, null);
        //获取分页后当前页的数据
        System.out.println(page.getRecords());
        //获取分页后当前页的数量
        System.out.println(page.getSize());
        //获取数据库总数量
        System.out.println(page.getTotal());
        //获取一共多少页
        System.out.println(page.getPages());
        //当前是第多少页
        System.out.println(page.getCurrent());
        //MappedStatement的id
        System.out.println(page.getCountId());
        //最大每页分页限制,优先级高于分页插件内的maxlimit
        System.out.println(page.getMaxLimit());
        //排序信息
        System.out.println(page.getOrders());
    }

    /**
     * queryWrapper
     * 需求:查询用户中姓名包含"伤",密码为"123456",且年龄为19或者25或者29,查询结果按照年龄降序排序;
     */
    @Test
    public void queryWrapper() {
        Page<User> page1 = new Page<>(1, 2);
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.like("user_name", "伤")
                .eq("password", "123456")
                .in("age", 19, 25, 29).orderByDesc("age");
        Page<User> page = userMapper.selectPage(page1, wrapper);
        System.out.println(page);
        System.out.println(page.getRecords());
        //获取分页后当前页的数量
        System.out.println(page.getSize());
        //获取数据库总数量
        System.out.println(page.getTotal());
        //获取一共多少页
        System.out.println(page.getPages());
        //当前是第多少页
        System.out.println(page.getCurrent());
        //MappedStatement的id
        System.out.println(page.getCountId());
        //最大每页分页限制,优先级高于分页插件内的maxlimit
        System.out.println(page.getMaxLimit());
        //排序信息
        System.out.println(page.getOrders());
    }

    /**
     * 1.通过QueryWrapper多条件查询时,默认使用and关键字拼接SQL;
     * 2.通过QueryWrapper调用or()方法时,底层会使用or关键字拼接方法左右的查询条件
     * 业务要求:查询用户名为"liuyan"或者年龄大于23的用户信息;
     */
    @Test
    public void queryWrapperOr() {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("user_name", "liuyan").or().gt("age", 23);
        List<User> users = userMapper.selectList(userQueryWrapper);
        System.out.println("users = " + users);
    }

    /**
     * QueryWrapper模糊查询like
     * 模糊查询有三个分别为左边添加%    右边添加%   两边都不添加%     分别对应likeLeft   likeRight  like
     * like("表列名","条件值");     作用:查询包含关键字的信息,底层会自动添加匹配关键字,比如:%条件值%
     * likeLeft("表列名","条件值"); 作用:左侧模糊搜索,也就是查询以指定条件值结尾的数据,比如:%条件值
     * likeRight("表列名","条件值");作用:右侧模糊搜索,也就是查询以指定条件值开头的数据,比如:条件值%
     */
    @Test
    public void queryWrapperLike() {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.like("user_name", "伤").ne("user_name", "赵一伤");
        List<User> users = userMapper.selectList(userQueryWrapper);
        System.out.println("users = " + users);
    }

    /**
     * 04-5-QueryWrapper排序查询
     * orderByAsc  	升序排序
     * orderByDesc 	降序排序
     */
    @Test
    public void queryWrapperOrder() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("age").orderByAsc("id");
        List<User> users = userMapper.selectList(wrapper);
        System.out.println("users = " + users);
    }

    /**
     * 04-6-QueryWrapper限定字段查询
     * MP查询时,默认将表中所有字段数据映射查询,但是有时我们仅仅需要查询部分字段信息,这是可以使用select()方法限定返回的字段信息,避免I/O资源的浪费;
     * wrapper.select("字段1","字段2",......)
     */
    @Test
    public void queryWrapperSelect() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.select("id", "name", "user_name");
        List<User> users = userMapper.selectList(wrapper);
        System.out.println("users = " + users);
    }

    /**
     * LambdaQueryWrapper查询
     * 1.使用QueryWrapper查询数据时需要手写对应表的列名信息,及其容易写错,开发体验不好;
     * 2.使用QueryWrapper查询数据时,表的列名硬编码书写,后期一旦表结构更改,则会带来很大的修改工作量,维护性较差;
     * 个人理解就是因为上边是将名字写死了,比如user_name对应数据库就是user_name,但是如果可以对应实体类那么就可以使用@TableFiled这个注解更改名字
     * 这样如果数据库字段名有更改,可以去改注解的名称
     */
    @Test
    public void lambdaQueryWrapper() {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUserName, "liuyan");
        List<User> users = userMapper.selectList(wrapper);
        System.out.println("users = " + users);
    }

    /**
     * 如果不写条件,那么就是更改的整个数据库的内容都会改变,注意写条件
     * 使用wrapper其实就是将写入的内容当作条件并不能充当改变的数据
     */
    @Test
    public void update() {
        UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
        //userUpdateWrapper.eq("id","2");
        User user = new User(null, "2", "3", "4", 5, "6");
        int update = userMapper.update(user, userUpdateWrapper);
        System.out.println("update = " + update);
    }

    @Test
    public void lambdaUpdateWrapper() {
        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(User::getId, "2");
        User user = new User(null, "2", "3", "4", 5, "6");
        int update = userMapper.update(user, wrapper);
        System.out.println("update = " + update);
    }

    @Test
    public void zuoye() {
        Page<User> page = new Page<>(1, 3);
        //查询全部
        List<User> list = userService.list();
        System.out.println("list = " + list);
        //分页查询全部
        Page<User> userPage = userService.page(page);
        System.out.println("userPage = " + userPage);
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(User::getId, 1, 2, 3, 3);
        //按照条件分页查询
        Page<User> page1 = userService.page(page, wrapper);
        System.out.println("page1.total = " + page1.getTotal());
        LambdaQueryWrapper<User> wrapperOne = new LambdaQueryWrapper<>();
        wrapperOne.eq(User::getId, 1);
        //getOne查询一条根据条件,如果数据库中符合条件的有多条那么就报错,必须符合条件的只有一条
        User one = userService.getOne(wrapperOne);
        System.out.println("one = " + one);
        //根据id查询
        User byId = userService.getById(1);
        System.out.println("byId = " + byId);
        //添加,如果id为nill那么就自动递增,默认是雪花算法
        boolean save = userService.save(new User(null, "2,", "3", "4", 5, "6"));
        System.out.println("save = " + save);
        //根据传入的实体类的id进行修改
        boolean b = userService.updateById(new User(17L, "2,", "3", "4", 5, "6"));
        System.out.println("b = " + b);
        LambdaUpdateWrapper<User> wrapperUpdate = new LambdaUpdateWrapper<>();
        wrapperUpdate.eq(User::getId, 1537832400332623874L);
        //根据条件修改
        boolean update = userService.update(new User(17L, "2,", "3", "4", 5, "90"), wrapperUpdate);
        System.out.println("update = " + update);
        //保存或者修改,如果有这个id那么就更新,如果没有那么就更改
        boolean saveOrUpdate = userService.saveOrUpdate(new User(18L, "2,", "3", "4", 5, "8"));
        System.out.println("saveOrUpdate = " + saveOrUpdate);
        //根据id删除
        boolean remove01 = userService.removeById(18);
        System.out.println("remove01 = " + remove01);
        //批量删除根据id
        ArrayList<Integer> relist1 = new ArrayList<>();
        Collections.addAll(relist1, 17, 16);
        boolean remove = userService.removeByIds(relist1);
        System.out.println("remove = " + remove);
        //根据条件删除
        LambdaUpdateWrapper<User> wrapper1 = new LambdaUpdateWrapper<>();
        wrapper1.eq(User::getId, 14);
        boolean remove1 = userService.remove(wrapper1);
        System.out.println("remove1 = " + remove1);
    }
}

实体类:这里有一个@TableName   @@TableFiled  集体看代码
 

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@TableName("tb_user")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User implements Serializable {
    /**
     * IdType.AUTO在数据库中的主键必须是自动递增而且还得是int数据类型
     * IdType.ASSIGN_ID   是雪花算法也是数据库默认的
     * IdType.ASSIGN_UUID 生成的随机数有字母和数字,所以主键在数据库中是String类型
     * mybatisplus默认的数据类型是雪花算法
     */
    //@TableId(type = IdType.AUTO)
    //@TableId(type = IdType.ASSIGN_UUID)
    private Long id;
    //@TableField("tname")
    private String userName;
    private String password;
    private String name;
    private Integer age;
    /**
     * 这个注解可以是指定名称,比如user这个实体类中email对应的字段在数据库中是email_1,
     * 那么可以使用@TableField("email_1")来指定
     * 如果email有值但是插入的时候又不想让这个email插入到数据库中,可以使用 @
     * TableField(exist = false)
     * 来讲email这个字段忽略插入这样不管email有没有值都会跳过
     *
     *UPDATE tb_user SET user_name=?, password=?, name=?, age=? WHERE id=?
     * 会发现如果使用了下边的注解 直接跳过   sql中根本不会出现email这个字段
     * 修改为例子
     * 并且这个注解只能当传入的是这个类的对象为参数的时候才可以
     */
    //@TableField("email_1")
    //@TableField(exist = false)
    private String email;
}

service实现层:因为ServiceImpl已经注入了Mapper,所以用到Mapper的时候不用注入了直接可以用底层的一个basemapper就相当于是Mapper层的    

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.mapper.UserMapper;
import com.itheima.pojo.User;
import com.itheima.service.UserService;
import org.springframework.stereotype.Service;

/**
 * 因为Uservice接口继承了Iservice接口,所以实现类在实现UserService的时候,也要实现Iservice这个接口,又因为ServiceImpl正好实现了这个Iservice这个接口所以就需要这样写
 * ServiceImpl的泛型第一个是UserMapper,因为这个泛型底层规定了<M extends BaseMapper<T>,正好UserMapper就是继承了BaseMapper
 * ServiceImpl把所有的都重写完了,因为里面有一个protected M baseMapper;  也就是传入的UserMapper那么M也就是UserMapper,这时候底层注入,那么也就是注入UserMapper,又因为UserMapper继承了
 * BaseMapper那么就调用BaseMapper的方法,这样ServiceImpl就完成了实现,然后这个实现类也可以baseMapper进行操作就不用注入UserMapper了因为UserMapper和baseMapper是等价的
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

}

Service层:

import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.pojo.User;

public interface UserService extends IService<User> {
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值