mybaits-plus笔记

Posted 敲代码的xiaolang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybaits-plus笔记相关的知识,希望对你有一定的参考价值。

目录

  • 前言
  • 1. 入门项目
    • 1.1 数据库
    • 1.2 项目构建
  • 2. 配置日志
  • 3. CURD基本用法
    • 3.1 插入操作
    • 3.2 更新操作
    • 3.3 删除操作
    • 3.4 查询操作
  • 4. ActiveRecord
    • 4.1 插入操作
    • 4.2 更新操作
    • 4.3 删除操作
    • 4.4 查询操作
  • 5. 表和列
    • 5.1 主键类型
    • 5.2 指定表名
    • 5.3 指定列名
  • 6. 自定义sql
  • 7. 查询和分页
    • 7.1 查询
    • 7.2 分页
  • 8. 代码生成器

前言

在学习mybatis-plus这篇文章时
需要掌握一些知识点

  1. java零基础从入门到精通(全)
  2. javaSE从入门到精通的二十万字总结(一)
  3. javaSE从入门到精通的二十万字总结(二)
  4. javaSE从入门到精通的二十万字总结(三)

以及

  1. Spring框架从入门到学精(全)
  2. SpringMVC从入门到精通(全)
  3. springboot从入门到精通(全)
  4. Mybatis从入门到精通(全)
  5. Maven详细配置(全)
  6. Maven实战从入门到精通(全)
  7. java中lambda表达式

这篇文章的学习知识点汇总主要通过该链接
MyBatis plus实战视频教程-带你快速掌握MyBatis-plus

主要的代码学习
可通过如下进行获取
mybatis_plus学习代码从入门到精通.rar

  • mybatis是直接执行sql语句,sql语句写在xml文件中,使用mybatis需
    要多个xml配置文件,在一定程度上比较繁琐。一般数据库的操作都要涉及到
    CURD
  • mybatis-plus是在mybatis上的增强,减少了xml的配置,几乎不用编写xml
    就可以做到单表的CURD,极大提供了开发的效率。而且提供了各种查询功能和分页行为

1. 入门项目

具体的步骤为

  • 创建工程,添加依赖
  • 创建实体类,定义属性,定义主键类型
  • 创建dao接口,继承BaseMapper实体类
  • 在启动类中加入扫描dao接口的包

在测试类中或者service注入dao接口,实现动态代理创建dao的实现类对象
调用BaseMapper中的方法,完成数据库的添加操作

1.1 数据库

先创建数据库文件

创建一个表

记得数据库的主键要设置一个自增的功能
不然会出现这种bug
出现Field ‘id‘ doesn‘t have a default value; nested exception is java.sql.SQLException的解决方法

在代码连接数据库中
代码要设置连接的端口账号密码以及数据库依赖文件等

先创建一个项目

在代码中创建连接数据库的配置文件

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/springdb?useUnicode=true&characterEncoding=utf-8
    username: root
    password: 123456 

需要额外引入mybatis-plus的依赖文件

<!-- mybatis-plus -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.0.5</version>
</dependency> 

以及数据库的依赖文件

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
    <version>5.1.6</version>
</dependency> 

此处数据库的相关部分就到这里

1.2 项目构建

接下来是构建一个实体类
实体类的名字要和数据库名字一样

@TableId(
        value="id",
        type = IdType.AUTO
)
private Integer id;
private String name;  // null
private String email;
//实体类属性,推荐使用包装类型, 可以判断是否为 null
private Integer age; // 0 

可以通过使用@data注解自动生成实体类get、set等方法
spring中@Data注解详细解析
也可以手动设置

可以看到实体类上面还有注解
大致意思是

  • value:主键字段的名称, 如果是id,可以不用写
  • type:指定主键的类型, 主键的值如何生成。 idType.AUTO 表示自动增长

mapper类,也就是DAO接口
要实现BaseMapper,指定实体类

public interface UserMapper extends BaseMapper<User> 
 

具体BaseMapper类的定义源码如下

主要是这个框架中的对象,定义17个操作方法(CRUD)

在启动类中还要加一个注解扫描为了扫描这个类
@MapperScan:扫描器,指定Mapper类所在的包

@SpringBootApplication
@MapperScan(value = "com.wkcto.plus.mapper")
public class PlusApplication 

    public static void main(String[] args) 
        SpringApplication.run(PlusApplication.class, args);
    
 

测试文件

关于@SuppressWarnings这个注解,主要是为了抑制警告值
具体信息可看我之前的文章
Spring中@SuppressWarnings注解详细解析

而对于@RunWith(SpringRunner.class),Test测试类要使用注入的类,比如@Autowired注入的类,才可实例化到spring容器

@SuppressWarnings("all")
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserTest 

    //定义StudentMapper
    @Autowired
    private UserMapper userDao;

    @Test
    public void testInsertStudent() 
        User user = new User();
        user.setName("zs");
        user.setEmail("zd.com");
        user.setAge(20);
        
        int rows = userDao.insert(user);
        System.out.println("inserStudent rows:" + rows);
    
 

2. 配置日志

在控制台打印日志
输出数据库的信息

主要在yml配置
具体信息为

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

3. CURD基本用法

完整代码就不书写了,只写核心代码

具体方法都是BaseMapper<T>这个类由来

3.1 插入操作

//添加数据后,获取主键值
@Test
public void testInsertGetId()
    User user  = new User();
    user.setName("李四");
    user.setAge(20);
    user.setEmail("lisi@163.com");

    int rows  = userDao.insert(user);
    System.out.println("insert user rows:"+rows);

    //获取主键id ,刚添加数据库中的数据的id
    int id = user.getId();//主键字段对应的get方法
    System.out.println("主键id:"+id);

 

3.2 更新操作

  • 如果属性用了多少,就会显示更新的多少
  • 最好用包装类型的类

在定义实体类的时候,最好使用包装类型,情况如下:

  • 定义实体类的基本类型,在如果没有更新,默认是会给0,也就是也更新了
  • 定义实体类包装类型,如果没有更新,默认是给null,但是更新的话,是更新的非null类型。
@Test
public void testUpdateUser()
    User user = new User();
    user.setName("修改的数据");
    user.setAge(22);
    user.setEmail("edit@163.com");
    user.setId(2);
    //执行更新,根据主键值更新
    /*UPDATE user SET name=?, email=?, age=? WHERE id=?
     *更新了所有非null属性值, 条件where id = 主键值
     */
    int rows = userDao.updateById(user);
    System.out.println("update rows:"+rows);
 

3.3 删除操作

  • 按主键删除一条数据
    方法是deleteById()
@Test
public void testDeleteById()

    //DELETE FROM user WHERE id=?
    int rows  = userDao.deleteById(3);
    System.out.println("deleteById:"+rows);
 
  • 按条件删除数据, 条件是封装到Map对象中
    方法是deleteByMap(map对象);
@Test
public void testDeleteByMap()
    //创建Map对象,保存条件值
    Map<String,Object> map  = new HashMap<>();
    //put("表的字段名",条件值) , 可以封装多个条件
    map.put("name","zs");
    map.put("age",20);
    //调用删除方法
    //DELETE FROM user WHERE name = ? AND age = ?
    int rows = userDao.deleteByMap(map);
    System.out.println("deleteByMap rows:"+rows);

 
  • 使用多个主键值,删除数据
    使用列表,方法是deleteBatchIds()
@Test
public void deleteByBatchId()
    List<Integer> ids  = new ArrayList<>();
    ids.add(1);
    ids.add(2);
    ids.add(3);
    ids.add(4);
    ids.add(5);

  
    //删除操作
    //DELETE FROM user WHERE id IN ( ? , ? , ? , ? , ? )
    int i = userDao.deleteBatchIds(ids);
    System.out.println("deleteBatchIds:"+i);

 

删除的话还可以使用lambda表达式
将其上面列表的代码替换为

 //使用lambda创建List集合
List<Integer> ids = Stream.of(1, 2, 3, 4, 5).collect(Collectors.toList()); 

3.4 查询操作

  • 根据主键值查询,方法是selectById
@Test
public void testSelectById()
    /**
     * 生成的sql: SELECT id,name,email,age FROM user WHERE id=?
     * 如果根据主键没有查找到数据, 得到的返回值是 null
     */
    User user = userDao.selectById(6);
    System.out.println("selectById:"+user);

    //在使用对象之前,需要判断对象是否为null
    if(user != null)
        //业务方法的调用
    

 
  • 实现批处理查询,根据多个主键值查询, 获取到List
    方法是selectBatchIds
@Test
public void testSelectBatchId()
    List<Integer> ids = new ArrayList<>();
    ids.add(6);
    ids.add(9);
    ids.add(10);

    //查询数据
    //SELECT id,name,email,age FROM user WHERE id IN ( ? , ? , ? )
    List<User> users = userDao.selectBatchIds(ids);
    System.out.println("size:"+users.size());
    for (User u:users)
        System.out.println("查询的用户:"+u);
    
 

也可以使用lambda表达式进行查询

List<Integer> ids = Stream.of(6, 9, 10, 15).collect(Collectors.toList()); 
  • 使用Map做多条件查询
    方法是selectByMap()
@Test
public void testSelectMap()
    //创建Map,封装查询条件
    Map<String,Object> map = new HashMap<>();
    //key是字段名, value:字段值 ,多个key,是and 联接
    map.put("name","zhangsan");
    map.put("age",20);

    //根据Map查询
    //SELECT id,name,email,age FROM user WHERE name = ? AND age = ?
    List<User> users = userDao.selectByMap(map);
    users.forEach(user -> 
        System.out.println("selectByMap:"+user);
    );

 

4. ActiveRecord

  • ActiveRecord负责把自己持久化,在ActiveRecord 中封装了对数据库的访
    问,通过对象自己实现CRUD,实现优雅的数据库操作
  • ActiveRecord 也封装了部分业务逻辑。可以作为业务对象使用

以下章节同样也是讲增上改查的用法(就不列举出小标题了)

主要的区别在于

  • 前者需要注入mapper以及使用mapper中继承的类(实现curd)
  • 现在是不需要注入mapper,而是通过实体类继承extends Model<Dept>,之后调用model中类来实现curd
//不需要
//使用自动注入, 注入Mapper对象(Dao)
@Autowired
private UserMapper userDao; 

查看model类中的源码

和原先步骤一样

  • 在数据库中创建表
  • 在代码中创建同样属性的实体类

使用AR,要求实体类需要继承MP中的Model,Model中提供了对数据库的CRUD的操作

mapper文件也要书写一下
因为DeptMapper是不需要使用的,MP需要使用DeptMapper获取到数据库的表的信息。
如果不定义DeptMapper, MP会报错, 找不到表的定义信息

public interface DeptMapper extends BaseMapper<Dept> 
 

测试类记得要加上这个注解

对于@RunWith(SpringRunner.class),Test测试类要使用注入的类,比如@Autowired注入的类,才可实例化到spring容器

具体测试类如下

4.1 插入操作

调用的是model中的insert方法

@Test
public void testARInsert()
    //定义dept的实体

    Dept dept  = new Dept();
    dept.setName("行政部");
    dept.setMobile("010-66666666");
    dept.setManager(5);
    //调用实体对象自己的方法,完成对象自身到数据库的添加操作
    boolean flag = dept.insert();
    System.out.println("ar insert result:"+flag);
 

4.2 更新操作

@Test
public void testARUpdate()
    //定义实体Dept
    Dept dept  = new Dept();
   // dept.setId(2);
    dept.setMobile("010-22222222");
    dept.setName("改为市场部");
    dept.setManager(2);
    //根据主键id更新记录
    // UPDATE dept SET name=?, mobile=?, manager=? WHERE id=?  // id = 1
    boolean result = dept.updateById();//使用dept实体主键的值,作为where id = 1
    System.out.println("ar updateById result:"+result);
 

书写多少个属性就更新多少个属性(前提属性的定义都是包装类型)

@Test
public void testARUpdate2()
    //定义实体Dept
    Dept dept  = new Dept();
   // dept.setId(1);
    dept.setMobile("010-3333333");
    //name , manager是没有修改的

    //根据主键id更新记录
    // UPDATE dept SET name=?, mobile=?, manager=? WHERE id=?  // id = 1
    // null的属性值不做更新处理,在update中没有null的字段
    //UPDATE dept SET mobile=? WHERE id=?
    boolean result = dept.updateById();//使用dept实体主键的值,作为where id = 1
    System.out.println("ar updateById result:"+result);
 

4.3 删除操作

  • deleteById()删除操作即使没有从数据库中删除数据,也返回是true
@Test
public void testARDeleteById()
    Dept dept  = new Dept();
    //DELETE FROM dept WHERE id=?
    boolean result = dept.deleteById(1);
    System.out.println("ar deleteById result:"+result);
 

4.4 查询操作

方法selectByID

  • 按实体的主键能查找出数据,返回对象
  • 按实体的主键不能查出数据,是null ,不报错
  • 没有记录或者没有数据也是返回null
@Test
public void testARSelectById()
    Dept dept = new Dept();
    //设置主键的值
  // dept.setId(1);
    //调用查询方法
   //SELECT id,name,mobile,manager FROM dept WHERE id=?
   Dept dept1 = dept.selectById();
   System.out.println("ar selectById result:"+dept1);


@Test
public void testARSelectById2()
    Dept dept = new Dept();
    Dept dept1 = dept.selectById(3);
    System.out.println("dept1:"+dept1);

 

5. 表和列

主要讲解一些实体类上的属性定义和数据库不一致的话
分别为这三个属性
主键,TableName, Tableld

5.1 主键类型

IdType的枚举类型如下

public enum IdType 
    AUTO(0),
    NONE(1),
    INPUT(2),
    ID_WORKER(3),
    UUID(4),
    ID_WORKER_STR(5);

    private int key;

    private IdType(int key) 
        this.key = key;
    

    public int getKey() 
        return this.key;
    
 
  • 0.none没有主键
  • 1.auto自动增长(mysql,sql server)
  • 2.input手工输入
  • 3.id_worker:实体类用Long id ,表的列用bigint , int类型大小不够
  • 4.id_worker_str 实体类使用String id,表的列使用varchar 50
  • 5.uuid 实体类使用String id,列使用varchar 50

5.2 指定表名

定义实体类,默认的表名和实体类同名

  • 如果不一致,在实体类定义上面使用
    @TableName(value=“数据库表名”)

主要区别在于
定义实体类的时候使用的类名
如果不符合数据库表名要加上这个注解
数据库表名为user_address

5.3 指定列名

主要通过这个注解

@TableField(value = "数据库属性名") 

MyBatis 默认支持这种规则
列名使用下划线,属性名是驼峰命名方式

大致意思就是(举个例子)

  • 列名使用custName
  • 数据库名使用cust_name

6. 自定义sql

和前面的思路一样
主要区别在于方法的定义以及mapper文件的映射等

mapper文件的继承

public interface StudentMapper extends BaseMapper<Student> 
    //自定义方法
    public int insertStudent(Student student);
    public Student selectStudentById(Integer id);
    public List<Student> selectByName(String name);
 

方法的定义在resources文件下

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wkcto.plus.mapper.StudentMapper">
    <insert id="insertStudent">
        insert into student(name,age,email,status) values(#name,#age,#email,#status)
    </insert>

    <select id="selectStudentById" resultType="com.wkcto.plus.entity.Student">
        select id,name,age,email,status from student where id=#studentId
    </select>

    <select id="selectByName" resultType="com.wkcto.plus.entity.Student">
        select id,name,age,email,status from student where name=#name
    </select>
</mapper> 

文件的具体位置是这个

但是这样定义要让代码识别到
所以要在application.yml配置文件中加入路径

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

此处重点讲解一下CURD数据库的编写细节

  • 名称空间要用mapper文件定义方法的全限定名称<mapper namespace="com.wkcto.plus.mapper.StudentMapper">
  • curd的方法id要用其类中定义的方法名,比如insertStudent方法等
  • resultType返回类型是实体类中的全限定名称名

7. 查询和分页

具体使用Wrapper

条件有:

条件描述
allEq基于map相等
eq等于
ne不等于
gt大于
ge大于等于
lt小于
le小于等于
between介值中间
notBetween不在这介值中间
likelike ‘%值%’
not likenot like ‘%值%’
likeLeftlike ‘%值’
likeRightlike ‘值%’
isNull字段 is null
isNotNull字段 is not null
in字段 in(value1,value2,。。)
notIn字段 not in(value1,value2,。。)
inSql字段 in(sql 语句) 例如 insql(“age”,“1,2,3”)–>age in(1,2,3,4,5,6) 或者 insql(“id”,“select id from table where id < 3”)–>id in(select id from table where id < 3)
notInSql字段 not in (sql 语句)
groupBygroup by 字段
orderByAsc升序 order by字段,…ASC
orderByDesc降序 order by 字段,…DESC
orderBy自定义字段排序 orderBy (true,true,“id”,“name”)—>order by id ASC,name ASC
having条件分组
oror 语句,拼接+or 字段=值
andand 语句,拼接+and 字段=值
apply拼接sql
last在sql语句后拼接自定义条件
exists拼接exists(sql 语句) 例:exists(“select id from table where age=1”)—>exists(select id from table where age=1)
notExists拼接not exists (sql 语句)
nested正常嵌套 不带and 或者or
  • select 设置查询字段select后面内容
  • set 设置要更新的字段,mp拼接sql语句
  • setSql 参数是sql语句,mp不在处理语句

7.1 查询

主要展示上面条件配合代码该如何实现

allEq
查询全部

@Test
public void testAllEq() 
    QueryWrapper<Student> qw = new QueryWrapper<>();
    //组装条件
    Map<String, Object> param = new HashMap<>();
    //map<key,value> key列名 , value:查询的值
    param.put("name", "张三");
    param.put("age", 22);
    param.put("status", 1);

    qw.allEq(param);
    //调用MP自己的查询方法
    //SELECT id,name,age,email,status FROM student WHERE name = ? AND age = ?
    //WHERE name = ? AND age = ? AND status = ?
    List<Student> students = studentDao.selectList(qw);
    students.forEach(stu -> System.out.println(stu));
 

如果有null的情况

  • Map对象中有 key的value是null,使用的是 qw.allEq(param,true);,结果:WHERE name = ? AND age IS NULL
  • Map对象中有 key的value是null,qw.allEq(param,false);结果:WHERE name = ?

结论: allEq(map,boolean)

  • true:处理null值,where 条件加入 字段 is null
  • false:忽略null ,不作为where 条件
@Test
public void testAllEq2() 
    QueryWrapper<Student> qw = new QueryWrapper<>();
    //组装条件
    Map<String, Object> param = new HashMap<>();
    //map<key,value> key列名 , value:查询的值
    param.put("name", "张三");
    //age 是 null
    param.put("age", null);

    //allEq第二个参数为true
    qw.allEq(param, false);

    //调用MP自己的查询方法
    List<Student> students = studentDao.selectList(qw);
    students.forEach(stu -> System.out.println(stu));
 

符号判断

//eq("列名",值) 等于
@Test
public void testEq() 
    QueryWrapper<Student> qw = new QueryWrapper<>();
    //组成条件
    qw.eq("name", "李四");
    //WHERE name = ?
    List<Student> students = studentDao.selectList(qw);
    students.forEach(stu -> System.out.println("查询eq:" + stu));



//ne不等于
@Test
public void testNe() 
    QueryWrapper<Student> qw = new QueryWrapper<>();
    //组成条件
    qw.ne("name", "张三");
    // WHERE name <> ?
    List<Student> students = studentDao.selectList(qw);
    students.forEach(stu -> System.out.println("查询ne:" + stu));


//gt 大于
@Test
public void testGt() 
    QueryWrapper<Student> qw = new QueryWrapper<>();
    qw.gt("age", 30); //age > 30
    // WHERE age > ?
    List<Student> students = studentDao.selectList(qw);
    students.forEach(stu -> System.out.println("stu:" + stu));


//ge 大于等于
@Test
public void testGe() 
    QueryWrapper<Student> qw = new QueryWrapper<>();
    qw.ge("age", 31);// >=31
    //WHERE age >= ?
    List<Student> students = studentDao.selectList(qw);
    students.forEach(stu -> System.out.println("student:" + stu));


//lt 小于
@Test
public void testLt() 
    QueryWrapper<Student> qw = new QueryWrapper<>();
    qw.lt("age", 32);
    // WHERE age < ?
    List<Student> students = studentDao.selectList(qw);
    students.forEach(stu -> System.out.println("student:" + stu));


//le  小于等于
@Test
public void testLe() 
    QueryWrapper<Student> qw = new QueryWrapper<>();
    qw.le("age", 32);
    //  WHERE age <= ?
    List<Student> students = studentDao.selectList(qw);
    students.forEach(stu -> System.out.println("student:" + stu));
 

区间范围内

//介值
@Test
public void testBetween() 
    QueryWrapper<Student> qw = new QueryWrapper<>();
    //between("列名",开始值,结束值)
    qw.between("age", 22, 28);
    // where age >= 12 and age < 28
    List<Student> students = studentDao.selectList(qw);
    students.forEach(stu -> System.out.println(stu));


//不在介值
@Test
public void testNotBetween() 
    QueryWrapper<Student> qw = new QueryWrapper<>();
    qw.notBetween("age", 18, 28);
    //WHERE age NOT BETWEEN ? AND ?
    // where age < 18 or age > 28
    List<Student> students = studentDao.selectList(qw);
    students.forEach(stu -> System.out.println(stu));
 

匹配字段

/**
 * like 匹配某个值
 */
@Test
public void testLike() 
    QueryWrapper<Student> qw = new QueryWrapper<>();
    qw.like("name", "张");
    // WHERE name LIKE %张%
    List<Student> students = studentDao.selectList(qw);
    students.forEach(stu -> System.out.println(stu));


/**
 * notLike 不匹配某个值
 */
@Test
public void testNotLike() 
    QueryWrapper<Student> qw = new QueryWrapper<>();
    qw.notLike("name", "张");
    //  WHERE name NOT LIKE ?  %张%
    List<Student> students = studentDao.selectList(qw);
    students.forEach(stu -> System.out.println(stu));


/**
 * likeLeft "%值"
 */
@Test
public void testLikeLeft() 
    QueryWrapper<Student> qw = new QueryWrapper<>();
    qw.likeLeft("name", "张");
    //WHERE name LIKE %张
    List<Student> students = studentDao.selectList(qw);
    students.forEach(student -> System.out.println(student));


/**
 * likeRight "%值"
 */
@Test
public void testLikeRight() 
    QueryWrapper<Student> qw = new QueryWrapper<>();
    qw.likeRight("name", "李");
    //WHERE name LIKE 李%
    List<Student> students = studentDao.selectList(qw);
    students.forEach(student -> System.out.println(student));


/**
 * isNull , 判断字段是 null
 */
@Test
public void testIsNull()
    QueryWrapper<Student> qw = new QueryWrapper<>();
    //判断email is null
    //WHERE email IS NULL
    qw.isNull("email");
    print(qw);


/**
 * isNotNull , 判断字段是 is not null
 */
@Test
public void testIsNotNull()
    QueryWrapper<Student> qw = new QueryWrapper<>();
    // WHERE email IS NOT NULL
    qw.isNotNull("email");
    print(qw);


private void print(QueryWrapper qw)
    List<Student> students = studentDao.selectList(qw);
    students.forEach(student -> System.out.println(student));
 

in 或者子查询

/**
 * isNull , 判断字段是 null
 */
@Test
public void testIsNull()
    QueryWrapper<Student> qw = new QueryWrapper<>();
    //判断email is null
    //WHERE email IS NULL
    qw.isNull("email");
    print(qw);


/**
 * isNotNull , 判断字段是 is not null
 */
@Test
public void testIsNotNull()
    QueryWrapper<Student> qw = new QueryWrapper<>();
    // WHERE email IS NOT NULL
    qw.isNotNull("email");
    print(qw);


/**
 * in 值列表
 */
@Test
public void testIn()
    QueryWrapper<Student> qw = new QueryWrapper<>();
    //in(列名,多个值的列表)
    //WHERE name IN (?,?,?)
    qw.in("name","张三","李四","周丽");
    print(qw);



/**
 * notIn 不在值列表
 */
@Test
public void testNoIn()
    QueryWrapper<Student> qw = new QueryWrapper<>();
    //in(列名,多个值的列表)
    //WHERE name NOT IN (?,?,?)
    qw.notIn("name","张三","李四","周丽");
    print(qw);


/**
 * in 值列表
 */
@Test
public void testIn2()
    QueryWrapper<Student> qw = new QueryWrapper<>();
    List<Object> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    //WHERE status IN (?,?)
    qw.in("status",list);
    print(qw);



/**
 * inSql() : 使用子查询
 */
@Test
public void testInSQL()
    QueryWrapper<Student> qw = new QueryWrapper<>();
    //WHERE age IN (select age from student where id=1)
    qw.inSql("age","select age from student where id=1");
    print(qw);


/**
 * notInSql() : 使用子查询
 */
@Test
public void testNotInSQL()
    QueryWrapper<Student> qw = new QueryWrapper<>();
    //WHERE age NOT IN (select age from student where id=1)
    qw.notInSql("age","select age from student where id=1");
    print(qw);


private void print(QueryWrapper qw)
    List<Student> students = studentDao.selectList(qw);
    students.forEach(student -> System.out.println(student));
 

分组

/**
 * groupBy:分组
 */
@Test
public void testGroupby()
    QueryWrapper<Student> qw = new QueryWrapper<>();
    qw.select("name,count(*) personNumbers");//select name,count(*) personNumbers
    qw.groupBy("name");
    // SELECT name,count(*) personNumbers FROM student GROUP BY name
    print(qw);
 

字段升序降序

/**
 * orderbyAsc : 按字段升序
 */
@Test
public void testOrderByAsc()
    QueryWrapper<Student> qw= new QueryWrapper<>();
    //FROM student ORDER BY name ASC , age ASC
    qw.orderByAsc("name","age");
    print(qw);


/**
 * orderbyDesc : 按字段降序
 */
@Test
public void testOrderByDesc()
    QueryWrapper<Student> qw= new QueryWrapper<>();
    // ORDER BY name DESC , id DESC
    qw.orderByDesc("name","id");
    print(qw);


/**
 * order :指定字段和排序方向
 *
 * boolean condition : 条件内容是否加入到 sql语句的后面。
 * true:条件加入到sql语句
 * FROM student ORDER BY name ASC
 *
 * false:条件不加入到sql语句
 * FROM student
 */
@Test
public void testOrder()
    QueryWrapper<Student> qw = new QueryWrapper<>();
    qw.orderBy(true,true,"name")
            .orderBy(true,false,"age")
            .orderBy(true,false,"email");
    // name asc, age desc , email desc
    //FROM student ORDER BY name ASC , age DESC , email DESC
    print(qw);
 

拼接以及存在与否

/**
 * and ,or方法
 */
@Test
public void testOr()
    QueryWrapper<Student> qw= new QueryWrapper<>();
    //WHERE name = ? OR age = ?
    qw.eq("name","张三")
            .or()
            .eq("age",22);
    print(qw);


/**
 * last : 拼接sql语句到MP的sql语句的最后
 */
@Test
public void testLast()
    QueryWrapper<Student> qw = new QueryWrapper<>();
    //SELECT id,name,age,email,status FROM student WHERE name = ? OR age = ? limit 1
    qw.eq("name","张三")
            .or()
            .eq("age",22)
            .last("limit 1");
    print(qw);



/**
 * exists : 判断条件
 *
 * notExists
 */
@Test
public void testExists()
    QueryWrapper<Student> qw= new QueryWrapper<>();
    //SELECT id,name,age,email,status FROM student
    // WHERE EXISTS (select id from student where age > 20)
    //qw.exists("select id from student where age > 90");

    //SELECT id,name,age,email,status FROM student WHERE
    // NOT EXISTS (select id from student where age > 90)

    qw.notExists("select id from student where age > 90");
    print(qw);
 

7.2 分页

/**
 * 分页:
 * 1.统计记录数,使用count(1)
 *    SELECT COUNT(1) FROM student WHERE age > ?
 * 2.实现分页,在sql语句的末尾加入 limit 0,3
 *    SELECT id,name,age,email,status FROM student WHERE age > ? LIMIT 0,3
 */
@Test
public void testPage()
    QueryWrapper<Student> qw = new QueryWrapper<>();
    qw.gt("age",22);
    IPage<Student> page  = new Page<>();
    //设置分页的数据
    page.setCurrent(1);//第一页
    page.setSize(3);// 每页的记录数

    IPage<Student> result = studentDao.selectPage(page,qw);

    //获取分页后的记录
    List<Student> students = result.getRecords();
    System.out.println("students.size()="+students.size());
    //分页的信息
    long pages  = result.getPages();
    System.out.println("页数:"+pages);
    System.out.println("总记录数:"+result.getTotal());
    System.out.println("当前页码:"+result.getCurrent());
    System.out.println("每页的记录数:"+result.getSize());
 

8. 代码生成器

这个有点像mybatis的逆向工程
详情可看我之前的文章
mybatis逆向工程详细配置讲解(全)

结合创建数据库的表,自动生成代码

添加依赖包

<!-- 模板引擎 -->
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.0</version>
</dependency> 

创建一个生成类

public class AutoMapper 

    public static void main(String[] args) 
        //创建AutoGenerator ,MP中对象
        AutoGenerator ag = new AutoGenerator();

        //设置全局配置
        GlobalConfig gc  = new GlobalConfig();
        //设置代码的生成位置, 磁盘的目录
        String path = System.getProperty("user.dir");
        gc.setOutputDir(path+"/src/main/java");
        //设置生成的类的名称(命名规则)
        gc.setMapperName("%sMapper");//所有的Dao类都是Mapper结尾的,例如DeptMapper
        //设置Service接口的命名
        gc.setServiceName("%sService");//DeptService
        //设置Service实现类的名称
        gc.setServiceImplName("%sServiceImpl");//DeptServiceImpl
        //设置Controller类的命名
        gc.setControllerName("%sController");//DeptController
        //设置作者
        gc.setAuthor("码农研究僧");
        //设置主键id的配置
        gc.setIdType(IdType.ID_WORKER);
        ag.setGlobalConfig(gc);

        //设置数据源DataSource
        DataSourceConfig ds  = new DataSourceConfig();
        //驱动
        ds.setDriverName("com.mysql.jdbc.Driver");
        //设置url
        ds.setUrl("jdbc:mysql://localhost:3306/springdb");
        //设置数据库的用户名
        ds.setUsername("root");
        //设置密码
        ds.setPassword("123456");
        //把DataSourceConfig赋值给AutoGenerator
        ag.setDataSource(ds);

        //设置Package信息
        PackageConfig pc  = new PackageConfig();
        //设置模块名称, 相当于包名, 在这个包的下面有 mapper, service, controller。
        pc.setModuleName("order");
        //设置父包名,order就在父包的下面生成
        pc.setParent("com.wkcto"); //com.wkcto.order
        ag.setPackageInfo(pc);

        //设置策略
        StrategyConfig sc  = new StrategyConfig();
        sc.setNaming(NamingStrategy.underline_to_camel);
        //设置支持驼峰的命名规则
        sc.setColumnNaming(NamingStrategy.underline_to_camel);
        ag.setStrategy(sc);

        //执行代码的生成
        ag.execute();
    
 

还要配置一个配置类

@Configuration
public class Config 

    /***
     * 定义方法,返回的返回值是java 对象,这个对象是放入到spring容器中
     * 使用@Bean修饰方法
     * @Bean等同于<bean></bean>
     */
    @Bean
    public PaginationInterceptor paginationInterceptor()
        return new PaginationInterceptor();
    
 

点击运行就会生成代码文件

执行测试类

@SuppressWarnings("all")
@RunWith(SpringRunner.class)
@SpringBootTest
public class StudentMapperTest 

   //注入生成的StudentMapper
    @Autowired
    StudentMapper studentMapper;

    @Test
    public void testInsertStudent()
        Student student  = new Student();
        student.setName("john");
        student.setAge(28);
        student.setEmail("john@yahu.com");
        student.setStatus(2);
        int rows  = studentMapper.insert(student);
        System.out.println("insert Student rows:"+rows);
    

    @Test
    public void testSelect()
        Student student = studentMapper.selectById(1);
        System.out.println("testSelect:"+student);
    

    @Test
    public void testSelect1()
        QueryWrapper<Student> qw = new QueryWrapper<>();
        qw.gt("age",35);
        //selectOne:查询结果只能是一条记录或没有没有记录,多条记录是报错的
        Student student = studentMapper.selectOne(qw);
        System.out.println("testSelect:"+student);
    
 

————————————————
版权声明:本文为CSDN博主「码农研究僧」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_47872288/article/details/121397544

以上是关于mybaits-plus笔记的主要内容,如果未能解决你的问题,请参考以下文章

mybaits-plus笔记

Mybaits-Plus插入核心代码

Mybaits-Plus插入核心代码

Mybaits-Plus操作CRUD

Mybaits-Plus操作CRUD

mybaits-plus常见配置