MyBatis-Plus(详解)

简介: MyBatis-Plus(详解)

🍁MyBatisPlus简介

  • MyBatisPlus(简称MP)是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提高效率。
  • 开发方式

    • 基于MyBatis使用MyBatisPlus
    • 基于Spring使用MyBatisPlus
    • 基于SpringBoot使用MyBatisPlus

🍁MyBatisPlus快速入门案例

  • 本案例采用SpringBoot整合MyBatis开发
  • 创建SpringBoot工程
  1. 创建过程在这就不过多描述,详细过程在Springboot专栏里👉点击直接查看
  2. 勾选配置使用的技

在这里插入图片描述

  1. 手动添加MP依赖:
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>

⭐⭐⭐注意:阿里云版本可以直接勾选MyBatisPlus

  1. 设置dataSource相关属性(JDBC参数)
spring:
  datasource:
    driver-class-name=com: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatisplus?serverTimezone=UTC
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

使用Druid数据源,需要导入坐标:

    <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.11</version>
        </dependency>
  1. 创建实体类(User)
package com.jkj.domain;
import lombok.Data;
@Data
public class User {
    private Long id;
    private String name;
    private String password;
    private Integer age;
    private String tel;
}
  1. 创建表结构

在这里插入图片描述

  1. 定义数据接口继承BaseMapper
package com.jkj.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jkj.domain.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserDao extends BaseMapper<User> {
}
  1. 创建测试类
@SpringBootTest
class Mybatisplus01ApplicationTests {

    @Autowired
    private UserDao userDao;
    @Test
    void findAll(){
        
        List<User> users = userDao.selectList(null);
        System.out.println(users);
       }
  }
  • 测试

在这里插入图片描述

🍁标准数据层开发

🔥MP接口

  • 新增:int insert(T t)
  • 删除:int deleteById(Serializable id)
  • 修改:int updateById(T t)
  • id查询:T selectById(Serializable id)
  • 查询全部:List<T> selectList()
  • 分页查询:IPage<T> selectPage( IPage<T> page)
  • 条件查询:Page<T> selectPage(Wrapper<T> querywrapper)

🔥 id查询

   @Test
    void findById(){
        User user = userDao.selectById(3L);
        System.out.println(user);
    }

测试:
在这里插入图片描述

🔥修改

@Test
    void updateById(){
        User user=new User();
        user.setId(2L);
        user.setName("老二");
        user.setTel("212121");
       userDao.updateById(user);
    }

测试:
在这里插入图片描述

🔥删除

   @Test
    void deleteById(){
        userDao.deleteById(4L);
    }

测试:
在这里插入图片描述

🔥保存

   @Test
    void save(){
        User user=new User();
        user.setId(4L);
        user.setName("老四");
        user.setPassword("444");
        user.setAge(67);
        user.setTel("555222");
        userDao.insert(user);
    }

测试:
在这里插入图片描述

🔥分页

  1. 设置分页拦截器作为Spring管理的bean
package com.jkj.config;
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 MpConfig {
   @Bean
   //设置分页拦截器
    public MybatisPlusInterceptor pageInterceptor(){
       //定义MP拦截器
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加具体的拦截器
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}
  1. 执行分页查询
  @Test
    void selectPage(){
        IPage page = new Page(1, 2);
        userDao.selectPage(page,null);
        System.out.println("当前页码"+page.getCurrent());
        System.out.println("每页数据总量"+page.getSize());
        System.out.println("总页数"+page.getPages());
        System.out.println("数据总量"+page.getTotal());
        System.out.println("当前页数据"+page.getRecords());

    }

测试:
在这里插入图片描述

🔥开启日志

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

🍁DQL控制

  • MyBatisPlus将书写复杂的sQL查询条件进行了封装,使用编程的形式完成查询条件的组合。

    • selectOneWrapper):T
    • selectCountWrapper): Integer
    • selectListWrapper): List
    • selectMapsWrapper): List<Map<String, Object> >
    • selectObjsWrapper): List
    • selectPage(IPage,Wrapper): IPage
    • selectMapsPage(IPage,Wrapper): lPage<Map<String, Object>>

🔥条件查询

🔥方式一按条件查询

        QueryWrapper qw = new QueryWrapper();
        qw.lt("age",20);
        List<User> users = userDao.selectList(qw);
        System.out.println(users);

🔥方式二:lambda格式按条件查询

        QueryWrapper<User> qw = new QueryWrapper<User>();
        qw.lambda().lt(User::getAge,20);
        List<User> users = userDao.selectList(qw);
        System.out.println(users);

🔥方式三:lambda格式按条件查询

        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.lt(User::getAge,20);
        List<User> users = userDao.selectList(lqw);
        System.out.println(users);

测试:
在这里插入图片描述

🔥并且and

  • 年龄大于20小于35
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.lt(User::getAge,35).gt(User::getAge,20);
        List<User> users = userDao.selectList(lqw);
        System.out.println(users);

测试:
在这里插入图片描述

🔥或者or

  • 小于20大于35
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.lt(User::getAge,20).or().gt(User::getAge,35);
        List<User> users = userDao.selectList(lqw);
        System.out.println(users);

测试:
在这里插入图片描述

🔥条件查询—null值处理

  • if语句控制条件追加
        LambdaQuerywrapper<User> lqw = new LambdaQuerywrapper<User>();
        if(null != userQuery.getAge()(
                  lqwn .ge(User::getAge,userQuery.getAge());
                   }
        if(null != userQuery.getAge2()){
                   lqw .lt(User::getAge,userQuery.getAge2());
                   }
        List<User> userList = userDao.selectList(lqw);
        System.out.print1n(userList);
  • 条件参数控制
        LambdaQuerywrapper<User> lqw = new LambdaQuerywrapper<User>();
        lqw.ge(null != userQuery.getAge(),User::getAge,userQuery.getAge());
        lqw.1t(null != userQuery.getAge2( ),User::getAge,userQuery.getAge2());
        List<User> userList = userDao.selectList( 1qw ) ;
        System.out.println(userList);
  • 条件参数控制(链式编程)
        LambdaQuerywrapper<User> lqw = new LambdaQuerywrapper<User>();
        lqw.ge(null != userQuery.getAge(),User::getAge,userQuery.getAge())
        .1t(null != userQuery.getAge2( ),user::getAge,userQuery.getAge2());
        List<User> userList = userDao.selectList( 1qw ) ;
        System.out.println(userList);

🔥查询投影

  • 查询结果包含模型类中部分属性
        //查询投影(方式一)
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.select(User::getId,User::getName,User::getAge);
        List<User> users = userDao.selectList(lqw);
        System.out.println(users);

        //查询投影(方式二)
        QueryWrapper qw = new QueryWrapper();
        qw.select("id","name","age");
        List<User> users = userDao.selectList(qw);
        System.out.println(users);

测试:
在这里插入图片描述

🔥 分组统计

        QueryWrapper qw = new QueryWrapper();
        qw.select("count(*) as count","tel");
        qw.groupBy("tel");
        List<Map<String,Object>> list = userDao.selectMaps(qw);
        System.out.println(list);

测试:
在这里插入图片描述

🔥 查询条件

  • 查询条件

    • 范围匹配(> = between )
    • 模糊匹配( like)
    • 空判定(null)
    • 包含性匹配 ( in )
    • 分组( group)
    • 排序( order)

    ....................

  • 模拟用户登录
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getName,"老二").eq(User::getPassword,"222");
        User user = userDao.selectOne(lqw);
        System.out.println(user);

测试:
在这里插入图片描述

🔥 范围查询

        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.between(User::getAge,10,35);
        List<User> users = userDao.selectList(lqw);
        System.out.println(users);

测试:
在这里插入图片描述

🔥 字段映射与表明映射

  • 当实体类属性和字段不一致时

    • @TableField
    • 属性注解
    • 设置当前属性对应的数据库表中的字段关系
    • value (默认〕:设置数据库表字段名称
@TableField(value = "psw")
    private String password;
  • 编码中添加了数据库中未定义的属性
  • exist:设置属性在数据表字段中是否存在,默认是true
@TableField(exist = false)
    private String address;
  • 查询字段的权限
  • select: 设置属性是否参与查询
 @TableField(value = "psw",select = false)
    private String password;
  • 表名与实体类名不一致
  • @TableName
  • 类注解
  • 设置当前类对应数据库表关系
@TableName("xfx_user")
public class User {
}
  • 在配置中解决表名与实体类名不一致的问题
mybatis-plus:
  global-config:
    db-config:
      id-type: auto
      table-prefix: xfx

🍁DML控制

🔥id生成策越

  • 名称:@TableId
  • 类型:属性注解
  • 位置:模型类中用于表示主键的属性定义上方
  • 作用:设置当前类中主键属性的生成策略
  • 相关属性

    • value:设置数据库主键名称
    • type:设置主键属性的生成策略,值参照IdType枚举值
    • AUTO(0):使用数据库id自增策略控制id生成
    • NONE(1):不设置id生成策略
    • INPUT(2):用户手工输入id
    • ASSIGN_ID(3):雪花算法生成id(可兼容数值型与字符串型)
    • ASSIGN_UUID(4):以UUID生成算法作为id生成策略
 @TableId(type = IdType.AUTO)
    private Integer id;

测试:

    @Test
    void save(){
        User user=new User();
        user.setName("老八");
        user.setAge(88);
        user.setPassword("888");
        user.setTel("6888867");
        userDao.insert(user);
    }

在这里插入图片描述

🔥多数据操作(删除)

    @Test
    void all(){
        List<Integer> list = new ArrayList<>();
        list.add(7);
        list.add(8);
        list.add(9);
        list.add(10);
        userDao.deleteBatchIds(list);
    }

删除前:
在这里插入图片描述
删除后:
在这里插入图片描述

🔥多数据操作(查询)

测试:

@Test
    void all(){
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(3);
        list.add(5);
        list.add(6);
        userDao.selectBatchIds(list);
    }

在这里插入图片描述

🔥逻辑删除

  • 数据表中添加删除标记字段

在这里插入图片描述

  • 实体类添加对应的字段,并设定字段为逻辑删除标记字段
    @TableLogic(value = "0",delval = "1")
    private Integer deleted;
  • 或者配置逻辑删除字面值
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      id-type: auto
      table-prefix: xfx
      logic-delete-field: deleted
      logic-not-delete-value: 0
      logic-delete-value: 1
  • 测试
    @Test
    void contextLoads() {
        userDao.deleteById(5);
    }
  • 执行sql语句

在这里插入图片描述

  • 测试结果

在这里插入图片描述

🔥乐观锁

乐观锁是对于数据冲突保持一种乐观态度,操作数据时不会对操作的数据进行加锁,只有到数据提交的时候才通过一种机制来验证数据是否存在冲突。乐观锁是通过在表中增加一个版本(version)或时间戳(timestamp)来实现,版本最为常用。乐观锁每次在执行数据的修改操作时,都会带上一个版本号,一旦版本号和数据的版本号一致就可以执行修改操作并对版本号执行 +1 操作,否则就执行失败。

  • 数据表中添加锁

在这里插入图片描述

  • 实体类添加对应的字段,并设定字段为逻辑删除标记字段
   @Version
   private Integer version;
  • 配置乐观锁拦截器机制对应的动态SQL语句拼装
@Configuration
public class MpConfig {
   @Bean
   //设置分页拦截器
    public MybatisPlusInterceptor pageInterceptor(){
       //定义MP拦截器
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加具体的拦截器
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        //乐观锁拦截器
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}
  • 使用乐观锁机制在修改前必须获取到对应数据的version方可正常运行
    @Test
    void contextLoads() {
        User user = userDao.selectById(1);
        user.setName("老大");
        userDao.updateById(user);
    }

在这里插入图片描述

  • 执行修改前先执行查询语句
SELECT id,name,age,tel,deleted,version FROM xfx_user WHERE id=? 
  • 执行修改时使用version字段作为乐观锁检查依据。
 UPDATE xfx_user SET name=?, age=?, tel=?, version=? WHERE id=? AND version=?
相关文章
|
8月前
|
XML Java 数据库连接
|
2天前
|
数据库
MyBatis-Plus中的QueryWrapper
MyBatis-Plus中的QueryWrapper
43 0
|
9月前
|
SQL XML 存储
MyBatis(上)
MyBatis(上)
|
11月前
|
SQL XML 存储
Mybatis总结
Mybatis总结
88 0
|
11月前
|
Java 数据库连接 mybatis
Mybatis小技巧
Mybatis小技巧
46 0
Mybatis-Plus中or()的使用
Mybatis-Plus中or()的使用
104 0
|
SQL XML 算法
|
SQL Java 数据库连接
mybatis 中的updateByPrimaryKey与updateByPrimaryKeySelective
mybatis 中的updateByPrimaryKey与updateByPrimaryKeySelective
|
SQL Java 数据库连接
|
SQL XML 搜索推荐