当前位置: 首页 > news >正文

MyBatis-plus笔记 (上)

简介

[MyBatis-Plus](简称 MP)是一个 [MyBatis]的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

mybatis-plus总结:

注意:mybatis-puls仅局限于单表操作。

  自动生成单表的CRUD功能

  提供丰富的条件拼接方式

  全自动ORM类型持久层框架

快速入门

代码举例:

正常创建一个springboot的工程

Application.yaml文件:

# 连接池配置

spring:

  datasource:

    type: com.alibaba.druid.pool.DruidDataSource

    druid:

      url: jdbc:mysql:///mybatis-example

      username: root

      password: abc123LQ

      driver-class-name: com.mysql.cj.jdbc.Driver

启动类:

@SpringBootApplication

@MapperScan("com.atguigu.mapper")

public class Main {

    public static void main(String[] args) {

        SpringApplication.run(Main.class,args);

        System.out.println("Hello world!");

    }

}

mapper接口:

/**

 * mybatis-plus使用步骤:

 * 正常创建实体类,创建mapper接口,注意此时不需要我们再创建mapper.xml文件了

 * 让mapper接口继承BaseMapper<实体类>

 *     BaseMapper 提供了增删改查的方法。

 */

public interface UserMapper extends BaseMapper<User> {

}

实体类:

测试类

/**

 * springboot测试类

 * 之前的测试类需要使用@SpringJUnitConfig(value = 配置类.class----------指定配置类

 * 现在只需加一个@SpringBootTest即可:

 *      自动帮我们完成ioc的初始化

 */

@SpringBootTest

public class SpringBootMybatisPlusTest {

    @Autowired

    private UserMapper userMapper;

    @Test

    public void test(){

        List<User> users = userMapper.selectList(null);

        System.out.println("users = " + users);

    }

}

基于baseMapper的crud增强 

通用 CRUD 封装BaseMapper接口, `Mybatis-Plus` 启动时自动解析实体表关系映射转换为 `Mybatis` 内部对象注入容器! 内部包含常见的单表操作!

Insert方法

// 插入一条记录

// T 就是要插入的实体对象

// 默认主键生成策略为雪花算法(后面讲解)

int insert(T entity);

|类型|

参数名|

描述|

|T|

entity|

实体对象|

Delete方法

// 根据 entity 条件,删除记录

int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);

// 删除(根据ID 批量删除)

int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

// 根据 ID 删除

int deleteById(Serializable id);

// 根据 columnMap 条件,删除记录

int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

|类型

|参数名

|描述|

|Wrapper<T>

|wrapper

|实体对象封装操作类(可以为 null)|

|Collection<? extends Serializable>

|idList|

主键 ID 列表(不能为 null 以及 empty)|

|Serializable

|id

|主键 ID|

|Map<String, Object>

|columnMap

|表字段 map 对象|

Update方法

注意:传入对象的属性为空时,元数据不做修改;所以建议再创建实体类时,将基础类型做为包装类型,

例如int age,如果该对象没有给id赋值的话,那么对象的id0而不是为空,这样再修改数据时就会将对象的id列修改为0

// 根据 whereWrapper 条件,更新记录

int update(@Param(Constants.ENTITY) T updateEntity,

            @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);//第一个装要修改的数据,第二个装修改条件

// 根据 ID 修改  主键属性必须值

int updateById(@Param(Constants.ENTITY) T entity);

|类型|

参数名|

描述|

|Wrapper<T>|

wrapper|

实体对象封装操作类(可以为 null)|

|Collection<? extends Serializable>

|idList|

主键 ID 列表(不能为 null 以及 empty)|

|Serializable|

id|

主键 ID|

|Map<String, Object>

|columnMap

|表字段 map 对象|

Select方法

// 根据 ID 查询

T selectById(Serializable id);

// 根据 entity 条件,查询一条记录

T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 查询(根据ID 批量查询)

List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

// 根据 entity 条件,查询全部记录

List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 查询(根据 columnMap 条件)

List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

// 根据 Wrapper 条件,查询全部记录

List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值

List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 entity 条件,查询全部记录(并翻页)

IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 Wrapper 条件,查询全部记录(并翻页)

IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 Wrapper 条件,查询总记录数

Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

|类型

|参数名

|描述|

|Serializable

|id|

主键 ID|

|Wrapper<T>

|queryWrapper|

实体对象封装操作类(可以为 null)|

|Collection<? extends Serializable>

|idList

|主键 ID 列表(不能为 null 以及 empty)|

|Map<String, Object>

|columnMap|

表字段 map 对象|

|IPage<T>

|page

|分页查询条件(可以为 RowBounds.DEFAULT)|

测试代码:

@SpringBootTest

public class MyBatisPlusTest {

    @Autowired

    private UserMapper userMapper;

    @Test

    public void test1(){

        User user = new User();

        user.setAge(88);

        user.setName("Jerry2");

        user.setEmail("test6@baomidou.com");

        int i = userMapper.insert(user);

        System.out.println("i = " + i);

    }

    @Test

    public void test2(){

        //根据id删除

        int i = userMapper.deleteById(6);

        System.out.println("i = " + i);

        //根据age=88 name=Jerry2删除

        HashMap map = new HashMap();

        map.put("age",88);

        map.put("name","Jerry2");

        int i1 = userMapper.deleteByMap(map);

        System.out.println("i1 = " + i1);

        //userMapper.delete(wrapper)

        //wrapper是条件封装对象,内部可以无限的封装条件

    }

    @Test

    public void test3(){

        //根据主键修改:updatebyId()传入的对象id必须又值

        // 将id=1的age改0为30

        User user = new User();

        user.setId(1L);

        user.setAge(30);

        int i = userMapper.updateById(user);

        System.out.println("i = " + i);

        //update() 传入对象可以没有id值

        //将所有人的年龄改为22

        User user1 = new User();

        user1.setAge(22);

        int update = userMapper.update(user1, null);//null代表每=没条件

        System.out.println("update = " + update);

    }

    @Test

    public void test4(){

        //通过id查询数据

        User user = userMapper.selectById(1);

        System.out.println("user = " + user);

        //根据ids集合查询

        List<Long> ids = new ArrayList<>();

        ids.add(1L);

        ids.add(2L);

        List list = userMapper.selectBatchIds(ids);

        System.out.println("list = " + list);

    }

}

 自定义与多表映射

mybatis-plus的默认mapperxml位置

mybatis-plus: # mybatis-plus的配置

  # 默认位置 private String[] mapperLocations = new String[]{"classpath*:/mapper/**/*.xml"};   

  mapper-locations: classpath:/mapper/*.xml

自定义mapper方法:

public interface UserMapper extends BaseMapper<User> {

    //正常自定义方法!

    //可以使用注解@Select或者mapper.xml实现

    List<User> queryAll();

}

基于mapper.xml实现:

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper

        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- namespace = 接口的全限定符 -->

<mapper namespace="com.atguigu.mapper.UserMapper">

   <select id="queryAll" resultType="user" >

       select * from user

   </select>

</mapper>

基于Service的crud增强

通用 Service CRUD 封装IService接口,进一步封装 CRUD 采用 `get 查询单行` `remove 删除` `list 查询集合` `page 分页` 前缀命名方式区分 `Mapper` 层避免混淆,

IService接口中提供了一般的crud的实现,一半没实现还是抽象方法,强制自定义实现另一半crud方法。

将另一半,没有实现的crud方法再ServiceImpl中实现了

对比Mapper接口CRUD区别:

- service添加了批量方法

- service层的方法自动添加事务

-mapper层重点是对单条数据的操作,而service层则增加了批量操作

步骤:

①实现IService接口

②继承ServiceImlp  ServiceImpl<实体类对应的Mapper接口, 实体类>

实现代码:

service接口

public interface UserService extends IService<User> {

}

service实现类

public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

}

CRUD方法测试代码:

@SpringBootTest

public class MyBatisPlusTest {

    @Autowired

    private UserService userService;

    @Test

    public void test_save(){

        List<User> list = new ArrayList<>();

        User user = new User();

        user.setAge(18);

        user.setEmail("JJ");

        user.setName("驴蛋蛋");

        list.add(user);

        User user1 = new User();

        user1.setAge(18);

        user1.setEmail("JJ");

        user1.setName("狗剩子");

        list.add(user1);

        boolean b = userService.saveBatch(list);

        System.out.println("b = " + b);

    }

    @Test

    public void test_saveOrUpdate(){

        //如果id有值那么就修改;没有就插入

        User user = new User();

        user.setAge(18);

        user.setEmail("JJ");

        user.setName("驴蛋蛋22");

        boolean b = userService.saveOrUpdate(user);

        System.out.println("b = " + b);

    }

    @Test

    public void test_remove(){

        boolean b = userService.removeById(1907418896856911874L);

        System.out.println("b = " + b);

    }

    @Test

    public void tes_update(){

        User user = new User();

        user.setId(1L);

        user.setAge(18);

        user.setEmail("JJ");

        user.setName("驴蛋蛋22");

        boolean b = userService.updateById(user);

        System.out.println("b = " + b);

    }

    @Test

    public void test_getOrList(){

        User byId = userService.getById(1L);//get返回的是单个对象

        List<User> list = userService.list(null);//查询全部,返回是的集合

    }

}

分页查询的使用

启动类:

@SpringBootApplication

@MapperScan("com.atguigu.mapper")

public class Main {

    public static void main(String[] args) {

        SpringApplication.run(Main.class,args);

    }

    /**

     * 将mybatis-plus插件导入到ioc容器步骤:

     * ①创建一个方法,在该方法中创建一个装所有插件的对象mybatisPlusInterceptor

     *          在方法中通过该对象添加想要的插件

     * ②返回该对象,同时将该对象加入到ioc容器中

     */

    //将mybatis-plus插件导入到ioc容器

    @Bean

    public MybatisPlusInterceptor plusInterceptor(){

        //创建一个mybatis-plus插件集合,所有的插件都集中在此(分页插件,乐观锁插件...)

        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();

        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

        return mybatisPlusInterceptor;

    }

}

测试类:

@SpringBootTest

@MapperScan("com.atguigu.mapper")

public class MyBatisPlusTest {

    /**

     * 使用分页插件的步骤:

     * ①带入插件(在启动类中)

     * ②使用:

     *     创建一个page对象,传入页码数与页容量,

     *     mapper接口中有一个查询+分页的方法selectPage(page,查询条件)

     *     最后分页查询的结果会封装在page中

     *     通过page调用方法,可以获得当前页的数据,总页数,页容量...

     */

    @Autowired

    private UserMapper userMapper;

    @Test

    public void test_page(){

        //创建一个page对象,传入页码数与页容量

        Page<User> page = new Page<>(1, 3);

        //mapper接口中有一个查询+分页的方法----------selectPage(page,查询条件)

        userMapper.selectPage(page,null);

        //selectPage(page,查询条件)此方法调用后,会将结果封装到page中

        long current = page.getCurrent();//获取当前页码

        long size = page.getSize();//获取页容量

        List<User> records = page.getRecords();//获取当前页的数据

        long total = page.getTotal();//获取总条数

        System.out.println(records);

    }

}

分页添加到自定义方法

①在mapper接口中正常自定义方法

注意此方法的放回值类型一定是IPage<实体类>,且定包含一个参数 IPage<实体类> pagepage对象用于装当前的页码数与页容量,最后返回结果也会封装到page对象。

②最后在mapper.xml文件中编写对应的sql语句

代码举例:

mapper接口:

public interface UserMapper extends BaseMapper<User> {

    //定义一个根据年龄参数查询,并且分页的方法 age > xx

   /**

     * 因为分页查询的结果会封装回page,所以方法的返回值填IPage<实体类>

     *     方法的形参要有一个IPage<实体类>的page对象,用来装当前页数与页容量,封装结果

     */

    IPage<User> queryByAge(IPage<User> page,@Param("age") Integer age);

}

Mapper.xml文件

<mapper namespace="com.atguigu.mapper.UserMapper">

    <!-- 查询结果填集合的泛型 -->

    <select id="queryByAge" resultType="user">

        <!-- sql语句不能添加分号,后面要拼接分页sql -->

        select * from user where age > #{age}

    </select>

</mapper>

 条件构造器与queryWrapper体验

条件构造器继承结构:

Wrapper : 条件构造抽象类,最顶端父类

- AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件

    - QueryWrapper : 查询/删除条件封装

    - UpdateWrapper : 修改条件封装

    - AbstractLambdaWrapper : 使用Lambda 语法

        - LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper

        - LambdaUpdateWrapper : Lambda 更新封装Wrapper

基于QueryWapper组装条件:

测试代码:

@SpringBootTest

@MapperScan("com.atguigu.mapper")

public class MybatisPlusQueryWrapperTest {

    @Autowired

    private UserMapper userMapper;

/** 包含某个字符条件,范围条件,不为空条件---------------------like(),between(),isNotNull()

 *     查询用户名包含a,年龄在2030之间,并且邮箱不为null的用户信息

 *     用queryWrapper实现:

 *         SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0

 *         AND (username LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)

 */

@Test

    public void test_01(){

        QueryWrapper<User> queryWrapper=new QueryWrapper<>();

        queryWrapper.like("name","a");

        queryWrapper.between("age",20,30);

        queryWrapper.isNotNull("email");

        //链式调用:

       // queryWrapper.like("name","a").between("age",20,30).isNotNull("email");

        List<User> users = userMapper.selectList(queryWrapper);

        System.out.println("users = " + users);

    }

    /**

     * 排序---------------orderByASC()

     * 按年龄降序查询用户,如果年龄相同则按id升序排列

     *  实现:

     *     SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE

     *     is_deleted=0 ORDER BY age DESC,id ASC

     */

    @Test

    public void test_02(){

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();

        queryWrapper.orderByDesc("age").orderByAsc("id");

        List<User> userList = userMapper.selectList(queryWrapper);

        System.out.println("userList = " + userList);

    }

    /**

     * or条件连接--------------------or()

     * 注意:多个条件之间默认用and拼接,想要使用or拼接,就调用or()

     *      or()第一个条件是or,其他的仍是and

     *  将年龄大于20并且用户名中包含有a或邮箱为null的用户信息修改

     *     UPDATE t_user SET age=?, email=? WHERE

     *     username LIKE ? AND age > ? OR email IS NULL)

     */

    /**

     * 查询指定列(默认查询所有列)-------------select(指定列)

     * //查询用户信息的nameage字段

     *     //SELECT name,age FROM t_user where id >1

     */

    @Test

    public void test_05(){

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();

        queryWrapper.select("name","age");

        queryWrapper.gt("id",1L);

        List<User> users = userMapper.selectList(queryWrapper);

        System.out.println("users = " + users);

    }

    /**

     * condition判断组织条件:(实现动态语句)

     * 每个方法夺回==都会有一个boolean condition,允许我们的一位放一个比较表达式 ;true 则整个条件生效 false 则不生效

     * 要求:前端传入两个参数 name age

     * name不为空,作为条件-查询

     * age>18,做为条件,查询等于 age=

     */

    @Test

    public void test6(){

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();

        String name="xx";

        Integer age=18;

        queryWrapper.eq(StringUtils.isNotBlank("name"),"name",name);

        queryWrapper.eq(age!=null&&age>18,"age",age);

        List<User> users = userMapper.selectList(queryWrapper);

        System.out.println("users = " + users);

    }

}

UpdateWrapper使用

@SpringBootTest

public class MyBatisPlusUpdateWrapperTest {

    @Autowired

    private UserMapper userMapper;

    /**

     * 使用queryWrapper修改值:

     * ①准备要修改的实体类数据

     * ②不能改为null

     * 使用UpdateWrapper

     * ①直接可以携带修改数据 set("列名","")

     * ②指定任意修改值

     */

    @Test

    public void test1(){

        UpdateWrapper<User> updateWrapper = new UpdateWrapper();

        updateWrapper.gt("age",20).like("name","a").or().isNull("email")

                .set("email",null)

                .set("age",90);

        int update = userMapper.update(null,updateWrapper);

        System.out.println("update = " + update);

    }

lambdaWrapper使用

LambdaQueryWrapperLambdaUpdateWrapper是对QueryWrapperUpdateWrapper的升级,增加了一个列名的提示:

我们可以使用lambda表达式来写列名,以防列名出现错误

lambda表达式回顾:

Lambda 表达式是 Java 8 引入的一种函数式编程特性,它提供了一种更简洁、更直观的方式来表示匿名函数或函数式接口的实现。Lambda 表达式可以用于简化代码,提高代码的可读性和可维护性。

Lambda 表达式的语法可以分为以下几个部分:

1 参数列表: 参数列表用小括号 () 括起来,可以指定零个或多个参数。如果没有参数,可以省略小括号;如果只有一个参数,可以省略小括号。

例如:(a, b), x ->, () ->

2 箭头符号: 箭头符号 -> 分割参数列表和 Lambda 表达式的主体部分。

3 Lambda 表达式的主体: Lambda 表达式的主体部分可以是一个表达式或一个代码块。如果是一个表达式,可以省略 return 关键字;如果是多条语句的代码块,需要使用大括号 {} 括起来,并且需要明确指定 return 关键字。

例如:单个表达式:x -> x * x

代码块:(x, y) -> { int sum = x + y; return sum; }

方法引用回顾:

方法引用是 Java 8 中引入的一种语法特性,它提供了一种简洁的方式来直接引用已有的方法或构造函数。方法引用可以替代 Lambda 表达式,使代码更简洁、更易读。

1 静态方法引用: 引用静态方法,语法为 类名::静态方法名。

2 实例方法引用: 引用实例方法,语法为 实例对象::实例方法名。

3 对象方法引用: 引用特定对象的实例方法,语法为 类名::实例方法名。

4 构造函数引用: 引用构造函数,语法为 类名::new

具体使用:

总结:"列名"=类名::getXXX

@SpringBootTest

public class MyBatisPlusLambdaQueryWrapperTest {

    @Autowired

    private UserMapper userMapper;

    @Test

    public void test_01(){

        QueryWrapper<User> queryWrapper=new QueryWrapper<>();

        queryWrapper.like("name","a");

        queryWrapper.between("age",20,30);

        queryWrapper.isNotNull("email");

        //lambdaQueryWrapper

        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();

        wrapper.like(User::getName,"a")

                .between(User::getAge,20,30)

                .isNotNull(User::getEmail);

        List<User> users = userMapper.selectList(wrapper);

        System.out.println("users = " + users);

    }

}

相关文章:

  • 深度学习中的数值稳定性处理详解:以SimCLR损失为例
  • 火山引擎旗下的产品
  • Simscape单摆模型搭建
  • 快速启动 Rust + WebAssembly 项目
  • [从零开始学数据库] 基本SQL
  • 谷歌发布大模型提示工程《Prompt Engineering》白皮书
  • STM32F4移植FATFS管理SD卡
  • AI测试引擎中CV和ML模型的技术架构
  • 【Linux】VIM 编辑器,编辑加速引擎
  • 赚钱的底层逻辑
  • 开关二极管热插拔保护方案
  • MySQL-存储引擎和索引
  • [dp11_最长子序列(不连续)] 最长数对链 | 最长定差子序列 最长的斐波那契子序列的长度
  • Nginx底层架构(非常清晰)
  • redis系列--1.redis是什么
  • qt(vs2010) 手动配置moc生成规则
  • 数据大屏只能撑撑场面?
  • Uniapp:本地存储
  • 卫星电话扬帆智慧海洋,构筑蓝海通信新生态
  • 48V/2kW储能电源纯正弦波逆变器详细设计方案-可量产
  • 市场监管总局召开企业公平竞争座谈会
  • 首季中国经济观察:一季度社融增量超15万亿元传递积极信号
  • 当美国掀翻了自己的全球化牌桌
  • 伊朗外交部:美矛盾立场被视为缺乏谈判的严肃性和诚意
  • 中超浙江队外援布彭扎意外坠楼身亡,加蓬总统发布讣告
  • 特斯拉上海超级工厂焕新版Model Y首次批量出口