MyBatis-Plus

MyBatis-Plus,第1张

MyBatis-Plus

目录

MyBatis-Plus介绍

入门案例

CRUD基本方法

ActiveRecord

表与列

主键的类型

指定表名

指定列名

驼峰命名

自定义SQL

查询构造器(Wrapper)

条件列表

查询

分页查询

MP代码生成器


MyBatis-Plus介绍

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 ​ MyBatis-Plus 在MyBatis 之上套了一层外衣,单表CURD 的 *** 作几乎都可以由 MyBatis-Plus 代替执行。而且提供了各种查询方式,分页行为。作为使用者无需编写xml,直接调用MyBatis-Plus 提供的API 就可以了。支持lambda表达式。底层是基于动态代理实现的。

官网:连接

入门案例

创建数据库mp ,创建user表,方便测试,数据库版本mysql8.X

 

将主键id设置为自增。

附加建表语句

CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(80) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `age` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

创建一个SpringBoot项目,pom.xml文件依赖

    
        
        
            org.springframework.boot
            spring-boot-starter
        
        
        
        
            mysql
            mysql-connector-java
            runtime
        
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

需要添加依赖

        
        
            com.baomidou
            mybatis-plus-boot-starter
            3.4.3.4
        

application.yml 添加数据库配置

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/数据库名?serverTimezone=GMT%2B8&&useUnicode=true&&characterEncoding=utf8&&useSSL=false&&nullCatalogMeansCurrent=true
    username: 数据库用户名
    password: 数据库密码

可以配置一个日志,方便程序的调试

# 添加日志,打印到控制台
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

这个日志,只会打印到控制台上,方便调试程序。

创建一个实体类User

public class User {
    // 定义属性名:属性名与表中列名一致
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    private String name;
    private Integer age;
    // set get toString方法
}

解析:

@TableId:设置主键的方式:

value:主键字段的名称, 如果是id,可以不用写

type:指定主键的类型,主键的值如何生成,IdType.AUTO:表示自动增长。

自定义一个Mapper接口,实现baseMapper,使用泛型指定实体类

import com.baomidou.mybatisplus.core.mapper.baseMapper;
import com.km.model.User;
​
public interface UserMapper extends baseMapper {
}

baseMapper 是MP框架中的对象,定义十几个CRUD *** 作方法.

需要在SpringBoot启动类上加入MapperScan注解,指定扫描的Mapper包,下面的案例也都需要。

@MapperScan("com.km.mapper")
@SpringBootApplication
public class MybatisPlusApplication {
    public static void main(String[] args) {        SpringApplication.run(MybatisPlusApplication.class, args);
    }
}

在测试类中,以添加为例测试

@SpringBootTest
class MybatisPlusApplicationTests {
    @Resource
    private UserMapper userMapper;
​
    @Test
    void testUserInsert() {
        User user = new User();
        user.setName("zhangsan");
        user.setAge(20);
        int insert = userMapper.insert(user);
        System.out.println("insert 的结果:" + insert);
    }
}

注意:这个注入UserMapper对象,使用的自动注入的方式

如果使用 @Autowired 注解,会出现下面这种现象

 

出现这种错误的原因,是因为找不到bean对象,因为这个bean是在程序执行过程中,才会创建的。

解决这个问题需要在方法上,添加一个@SuppressWarnings 注解,用来抑制警告

@SuppressWarnings("all") // 抑制警告

测试结果也符合预期。

CRUD基本方法 insert

与入门案例类似,下面只介绍需要改动的地方,打开日志,便于测试。

int insert(T entity);

解析:

参数:实体类

返回值:插入的行数

    // 添加数据后,获取主键值
    @Test
    void testUserInsertGetId() {
        User user = new User();
        user.setName("李四");
        user.setAge(25);
        int insert = userMapper.insert(user);
        // INSERT INTO user ( name, age ) VALUES ( ?, ? )
        System.out.println("insert 的结果:" + insert);
        Integer id = user.getId();
        System.out.println("主键的值:"+id);
    }

不仅可以添加一条数据,还可以返回添加这条数据的主键值。

测试与预期一致。

update

根据主键值更新

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

解析:

参数:实体对象

返回值:修改的数据条数

	@Test
    void testUpdateUser(){
        User user = new User();
        user.setAge(36);
        user.setName("张三");
        // 根据主键值更新
        user.setId(2);
        int result = userMapper.updateById(user);
        // UPDATE user SET name=?, age=? WHERe id=?
        System.out.println("更新行数:" + result);
    }

【注意】:更新属性,只更新非null字段的属性。下面案例:

    @Test
    void testUpdateUser2(){
        User user = new User();
        // 这里没有给age属性赋值
        user.setName("22");
        // 根据主键值更新
        user.setId(1);
        int result = userMapper.updateById(user);
        // UPDATE user SET name=? WHERe id=?
        System.out.println("更新行数:" + result);
    }

解析:因为底层对非空进行了判断处理。判断字段是否要修改,是根据属性值是否为null判断。

【注意】如果实体类是基本数据类型,如:int,就会改变数据库的数据值,变为0。

这就和属性的默认值有关系,如果是包装类型,默认值就会是null,底层就会对null进行判断处理,而int类型默认值是0。因此,属性类型推荐使用包装类型。

delete

根据主键删除一条数据

int deleteById(Serializable id);

解析:

参数:主键

返回值:删除的行数

    @Test
    void testDeleteById(){
        int row = userMapper.deleteById(2);
        // DELETE FROM user WHERe id=?
        System.out.println("删除行数:" + row);
    }

【注意】:删除条件封装在Map 中,key 是列名,value 是值,多个key 之间and 联接。

下面方法与上个方法类似

int deleteById(T entity);

解析:

参数:实体类

返回值:删除的行数

    @Test
    void testDeleteById(){
        User user = new User();
        user.setId(1);
        int row = userMapper.deleteById(user);
        // DELETE FROM user WHERe id=?
        System.out.println("删除行数:" + row);
    }

按条件删除,使用Map

int deleteByMap(@Param(Constants.COLUMN_MAP) Map columnMap);

解析:

参数:表字段 map 对象

返回值:根据 columnMap 条件,删除记录

    @Test
    void testDeleteByMap(){
        Map map = new HashMap<>();
        map.put("age",25);
        int result = userMapper.deleteByMap(map);
        // DELETE FROM user WHERe age = ?
        System.out.println("删除条数:" + result);
    }

批处理方式,使用多个主键值,删除数据

int deleteBatchIds(@Param(Constants.COLLECTION) Collection idList);

解析:

参数:主键列表(不能为 null 以及 实体类)

返回值:根据ID 批量删除成功的条数

    @Test
    void testDeleteBatchById(){
        List list = new ArrayList<>();
        list.add(7);
        list.add(8);
        list.add(9);
        int result = userMapper.deleteBatchIds(list);
        // DELETE FROM user WHERe id IN ( ? , ? , ? )
        System.out.println("删除条数:" + result);
    }

mybatis-plus支持lambda表达式

    @Test
    void testDeleteBatchById(){
        // 使用lambda创建List集合
        List list = Stream.of(7, 8, 9).collect(Collectors.toList());
        int result = userMapper.deleteBatchIds(list);
        // DELETE FROM user WHERe id IN ( ? , ? , ? )
        System.out.println("删除条数:" + result);
    }
select

根据主键值查询

T selectById(Serializable id);

解析:

参数:主键值

返回值:实体类

	@Test
    void testSelectById(){
        User user = userMapper.selectById(7);
        // SELECT id,name,age FROM user WHERe id=?
        System.out.println("查询 信息:" + user);
    }

【注意】:如果根据主键没有查找到数据,返回值是null,不会报错。需要在使用对象之前,进行非空判断。

批处理查询,根据多个主键值查询,获取到List

解析:

参数:主键值列表(不能为 null 以及 实体类)

返回值:根据主键值列表,批量查询List

    @Test
    void testSelectBatchById(){
        List list = new ArrayList<>();
        list.add(6);
        list.add(10);
        List users = userMapper.selectBatchIds(list);
        // SELECT id,name,age FROM user WHERe id IN ( ? , ? )
        System.out.println("查询数据个数:" + users.size());
    }

支持lambda表达式

    @Test
    void testSelectBatchById2(){
        List list = Stream.of(6,10).collect(Collectors.toList());
        List users = userMapper.selectBatchIds(list);
        // SELECT id,name,age FROM user WHERe id IN ( ? , ? )
        users.forEach(user -> {
            System.out.println("查询的user对象:" + user);
        });
    }

条件查询,使用Map

List selectByMap(@Param(Constants.COLUMN_MAP) Map columnMap);

解析;

参数:表字段,map对象

返回值:根据 columnMap 条件查询的List

    @Test
    void testSelectMap(){
        Map map = new HashMap<>();
        map.put("age",20);
        List users = userMapper.selectByMap(map);
        // SELECT id,name,age FROM user WHERe age = ?
        users.forEach(user -> {
            System.out.println("查询的user对象:"+user);
        });
    }
ActiveRecord

介绍:

  • 每一个数据库表对应创建一个类,类的每一个对象实例对应于数据库中 表的一行记录; 通常表的每个字段在类中都有相应的Field;

  • ActiveRecord 负责把自己持久化。在 ActiveRecord 中封装了对数据库的访 问,通过对象自己实现CRUD,实现优雅的数据库 *** 作。

  • ActiveRecord 也封装了部分业务逻辑。可以作为业务对象使用。

这里的案例与入门案例大体上类似,数据库mp,表user,SpringBoot项目,mybatis-plus依赖,mysql连接器依赖,配置数据库信息,打开日志配置,也可以直接按照下面的更改入门案例。

创建User实体类,并继承Model,使用泛型指定实体类

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.extension.activerecord.Model;
​
public class User extends Model {
    // 定义属性,属性名和表的列名一致
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    private String name;
    private Integer age;
    // set  get  toString方法
}

【注意】:使用AR,要求实体类需要继承MP中的Model,Model中提供了对数据库的CRUD的 *** 作。

import com.baomidou.mybatisplus.core.mapper.baseMapper;
import com.km.model.User;
​
public interface UserMapper extends baseMapper {
}

【注意】:UserMapper 是不需要使用的,但是MP需要使用UserMapper获取到数据库的表的信息。如果不定义UserMapper,MP会报错,找不到表的定义信息。

AR-insert

调用实体对象自己的方法,完成对象自身到数据库的添加 *** 作。

public boolean insert() {}
	@Test
    void testARInsert(){
        // 定义User实体类
        User user = new User();
        user.setName("张三");
        user.setAge(23);
        boolean flag = user.insert();
        // INSERT INTO user ( name, age ) VALUES ( ?, ? )
        System.out.println("结果:" + flag);
    }

添加成功返回true,失败返回false。

AR-update

根据主键更新数据

public boolean updateById() {}
	@Test
    void testARUpdate(){
        User user = new User();
        user.setId(14);
        user.setAge(20);
        user.setName("lisi");
        boolean flag = user.updateById(); // 使用user实体类主键的值,WHERe id=14
        // UPDATE user SET name=?, age=? WHERe id=?
        System.out.println("结果:"+ flag);
    }

更新成功返回true,失败返回false。

【注意】:属性值为null不做更新处理,update SQL语句中没有null的字段。

AR-delete

根据主键值,删除数据

public boolean deleteById(Serializable id) {}
	@Test
    void testARDeleteById(){
        User user = new User();
        boolean flag = user.deleteById(14);
        // DELETE FROM user WHERe id=?
        System.out.println("结果:"+flag);
    }

删除数据成功返回true,删除失败返回false。

根据对象自身主键属性的值

public boolean deleteById() {}
    @Test
    void testARDeleteById2(){
        User user = new User();
        user.setId(15);
        boolean flag = user.deleteById();
        // DELETE FROM user WHERe id=?
        System.out.println("结果:"+flag);
    }
AR-selete

使用查询 *** 作,需要实体类继承Model类时,添加泛型,方便 *** 作。

根据主键查找数据,带参数

public T selectById(Serializable id) {}
	@Test
    void testARSelectById(){
        User user = new User();
        // 设置主键的值
        user.setId(16);
        //调用查询方法
        User user1 = user.selectById();
        // SELECT id,name,age FROM user WHERe id=?
        System.out.println("查询结果:" + user1);
    }

【注意】:按实体的主键能查找出数据,返回对象,如果查询不到数据,返回null。

根据主键查找数据,不带参数

public T selectById() {}
    @Test
    void testARSelectById(){
        User user = new User();
        // 设置主键的值
        user.setId(16);
        //调用查询方法
        User user1 = user.selectById();
        // SELECT id,name,age FROM user WHERe id=?
        System.out.println("查询结果:" + user1);
    }
表与列 主键的类型
public enum IdType {
    AUTO(0),
    NONE(1),
    INPUT(2),
    ASSIGN_ID(3),
    ASSIGN_UUID(4);
}

解析:

AUTO:数据库ID自增

NONE:无状态

INPUT:插入前自行设置主键值

ASSIGN_ID:雪花算法

ASSIGN_UUID:排除中划线的UUID

AUTO,自动增长,前面案例用到过了

ASSIGN_ID(雪花算法)

如果不设置类型值,默认则使用IdType.ASSIGN_ID策略(自3.3.0起)。该策略会使用雪花算法自动生成主键ID,主键类型为长或字符串(分别对应的MySQL的表字段为BIGINT和VARCHAR)。

雪花算法(雪花)是分布式ID生成算法其核心思想就是:使用一个64位的长型的数字作为全局唯一ID。在分布式系统中的应用十分广泛,且ID引入了时间戳,基本上保持自增的。

修改实体类,主键类型

public class User extends Model {
    // 定义属性,属性名和表的列名一致
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private Integer id;
    private String name;
    private Integer age;
    // set get toString方法
}

更改数据库,与实体类对应

 

主键不需要自增。向数据库表中执行insert *** 作

 

上面这种类型是bigint类型,还可以使用varchar类型。

ASSIGN_UUID(排除中划线的UUID)

使用IdType.ASSIGN_UUID策略,并重新自动生成排除中划线的UUID作为主键。主键类型为String,对应MySQL的表分段为VARCHAR(32)

修改实体类

public class User extends Model {
    // 定义属性,属性名和表的列名一致
    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    private String id;
    private String name;
    private Integer age;
    // set get toString方法
}

更改数据库,与实体类对应

 

主键不需要自增。向数据库表中执行insert *** 作

 

指定表名

定义实体类,默认的表名和实体类同名;如果不一致,在实体类定义上面使用@TableName 说明表名称。

@TableName(value="表名")

解析:在类的上面使用

属性value 指定表的名字。

现在表的名字为 user_test,与实体类的名字不一致,使用@TableName注解,指定表的名字。

@TableName(value = "user_test")
public class User extends Model {
    // 定义属性,属性名和表的列名一致
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    private String name;
    private Integer age;
	//set get toString方法
}

执行insert语句,向数据库添加数据,底层执行

INSERT INTO user_test ( name, age ) VALUES ( ?, ? )

这里就不是使用默认的user表,而是指定的user_test表。

指定列名

实体类属性名和表的列名不一致的情况下,在实体类属性上面使用@TableField 说明表的列名。

@TableField(value = "列名")

解析:在实体类属性的上面使用

属性value 指定表的列名。

现在表的名字为user,但是表的列名与实体类属性不一致

 

使用@TableField注解,指定表的列名的名字。

public class User extends Model {
    
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
​
    @TableField(value = "user_name")
    private String name;
​
    @TableField(value = "user_age")
    private Integer age;
    // set get toString方法
}

执行insert语句,向数据库添加数据,底层执行

INSERT INTO user ( user_name, user_age ) VALUES ( ?, ? )

这里就不是使用默认的实体类的属性名,而是指定的表的列名。

驼峰命名

列名使用下划线,属性名是驼峰命名方式。这种方式是比较常见的,mybatis-plus 默认支持这种规则。

表user,列名使用 "_" 进行分隔。

 

实体类,属性名使用驼峰命名的方式。

public class User extends Model {
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    private String userName; //user_name
    private Integer userAge;  //user_age
    //set get toString方法
}

执行insert语句,向数据库添加数据,底层执行

INSERT INTO user ( user_name, user_age ) VALUES ( ?, ? )
自定义SQL

与入门案例类似,user表

 

实体类

public class User {
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    private String name;
    private Integer age;
    // set get toString方法
}

创建UserMapper接口,实现baseMapper,指定泛型,自定义mapper方法(mybatis的mapper),这里简单写一个插入语句,简单演示

public interface UserMapper extends baseMapper {
    int insertUser(User user);
}

在resources文件夹下,创建mapper文件夹,里面创建sql映射文件UserMapper.xml

 




    
        insert into user (name,age) values (#{name},#{age})
    

这里注意以下,在类路径(resources文件夹)下,建立一个mapper文件夹,这个mapper文件夹下的xml文件都会自动扫描,无需配置。

如果不成功可以在application.yml配置文件中配置

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

解析:这是指定mapper文件的位置。

测试这个方法

@SpringBootTest
class MybatisPlusCustomSQLTests {
​
    @Resource
    private UserMapper userMapper;
​
    @Test
    void testInsertUser(){
        User user = new User();
        user.setName("zhansgan");
        user.setAge(22);
        int result = userMapper.insertUser(user);
        // insert into user (name,age) values (?,?)
        System.out.println("结果:" + result);
    }
}

测试结果符合预期。

查询构造器(Wrapper)

分类:

  • QueryWrapper:查询条件封装类

  • UpdateWrapper:更新条件封装类

QueryWrapper(LambdaQueryWrapper) 和UpdateWrapper(LambdaUpdateWrapper) 的父类用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件。 MP3.x 开始支持lambda 表达式,LambdaQueryWrapper,LambdaUpdateWrapper支持lambda 表达式的构造查询条件。

条件列表 条件说明allEq基于map 的相等eq / ne等于(=) / 不等于(<>)gt / ge / lt / le大于(>) / 大于等于(>=) / 小于(<) / 小于等于(<=)between / notBetweenBETWEEN 值1 AND 值2 / NOT BETWEEN 值1 AND 值2like / notLikeLIKE '%值%' / NOT LIKE '%值%'likeLeft / likeRightLIKE '%值' / LIKE '值%'isNull / isNotNull字段 IS NULL / 字段 IS NOT NULLin / notIn字段 IN (value1, value2, ...) / 字段 NOT IN (value1, value2, ...)inSql / notInSql字段 IN ( sql 语句 ) / 字段 NOT IN ( sql 语句 )groupByGROUP BY 字段orderByAsc / orderByDesc升序ORDER BY 字段, ... ASC / 降序ORDER BY 字段, ... DESCorderBy自定义字段排序having条件分组orOR 语句,拼接 + OR 字段=值;andAND 语句,拼接 + AND 字段=值apply拼接 sqllast在sql 语句后拼接自定义条件exists / notExists拼接 EXISTS (sql 语句) / 拼接 NOT EXISTS (sql 语句)nested正常嵌套 不带 AND 或者 OR 查询

使用user表,主键设置为自增。

 

实体类User

public class User {
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    private String name;
    private Integer age;
    // set get toString方法
}

创建UserMapper接口,实现baseMapper,指定泛型类型

public interface UserMapper extends baseMapper {
}
allEq

基于map 的相等

map key 列名,value:查询的值

@Test
void testAllEq(){
    QueryWrapper qw = new QueryWrapper<>();
    //组装条件
    Map param = new HashMap<>();
    // map key 列名,value:查询的值
    param.put("name", "zhangsan");
    param.put("age",22);
    qw.allEq(param);
    // 调用MP自己的查询方法
    List users = userMapper.selectList(qw);
    users.forEach(user -> System.out.println(user));
}

底层执行sql,使用占位符的格式,参数“张三”,22 替换

SELECT id,name,age FROM user WHERe (name = ? AND age = ?)
allEq(map,boolean)

解析:第二个参数,是Boolean值

true:处理null值, where 条件加入 字段 is null。

底层行sql语句

SELECt id,name,age FROM user WHERe (name = ? AND age IS NULL)

false:忽略null, 不作为where 条件。

底层行sql语句

SELECt id,name,age FROM user WHERe (name = ?)
eq

等于 =

eq(R column, Object val){}

解析:

column:列名

val:值

@Test
void testEq(){
    QueryWrapper qw = new QueryWrapper<>();
    // 组成条件
    qw.eq("name", "zhangsan");
    List users = userMapper.selectList(qw);
    users.forEach(user -> System.out.println(user));
}

底层执行SQL

SELECT id,name,age FROM user WHERe (name = ?)
ne

不等于 <>

ne(R column, Object val){}

解析:

column:列名

val:值

@Test
void testNe(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.ne("name", "lisi");
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (name <> ?)
    users.forEach(user -> System.out.println(user));
}
gt

大于 >

@Test
void testGt(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.gt("age",20);
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (age > 20)
    users.forEach(user -> System.out.println(user));
}
ge

大于等于 >=

@Test
void testGe(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.ge("age",20);
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (age >= ?)
    users.forEach(user -> System.out.println(user));
}
lt

小于 <

@Test
void testLt(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.lt("age",20);
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (age < 20)
    users.forEach(user -> System.out.println(user));
}
le

小于等于 <=

@Test
void testLe(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.le("age",20);
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (age <= ?)
    users.forEach(user -> System.out.println(user));
}
between

between("列名",开始值,结束值)

@Test
void testBetween(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.between("age",22,33);
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (age BETWEEN ? AND ?)
    // where age >= 22 and age <= 33
    users.forEach(user -> System.out.println(user));
}
notBetween

notBetween("列名",开始值,结束值)

@Test
void testNotBetween(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.notBetween("age",22,33);
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (age NOT BETWEEN 22 AND 33)
    // where age < 22 and age > 33
    users.forEach(user -> System.out.println(user));
}
like

"%值%"

@Test
void testLike(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.like("name","z");
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (name LIKE ?)
    // SELECt id,name,age FROM user WHERe (name LIKE %z%)
    users.forEach(user -> System.out.println(user));
}
notLike
@Test
void testNotLike(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.notLike("name","z");
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (name NOT LIKE ?)
    // SELECt id,name,age FROM user WHERe (name NOT LIKE %z%)
    users.forEach(user -> System.out.println(user));
}
likeLeft

"%值"

@Test
void testLikeLeft(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.likeLeft("name","z");
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (name LIKE ?)
    // SELECt id,name,age FROM user WHERe (name LIKE %z)
    users.forEach(user -> System.out.println(user));
}
likeRight

"值%"

@Test
void testLikeRight(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.likeRight("name","z");
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (name LIKE ?)
    // SELECt id,name,age FROM user WHERe (name LIKE z%)
    users.forEach(user -> System.out.println(user));
}
isNull

判断字段是 null

@Test
void testIsNull(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.isNull("name");
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (name IS NULL)
    users.forEach(user -> System.out.println(user));
}   
isNotNull

判断字段是 is not null

@Test
void testIsNotNull(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.isNotNull("name");
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (name IS Not NULL)
    users.forEach(user -> System.out.println(user));
}
in

in("列名", 多个值的列表)

@Test
void testIn(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.in("name","lisi","zhangsan");
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (name IN (?,?))
    users.forEach(user -> System.out.println(user));
}
@Test
void testIn2(){
    QueryWrapper qw = new QueryWrapper<>();
    ArrayList list = new ArrayList<>();
    list.add(1);
    list.add(2);
    qw.in("id",list);
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (id IN (1,2))
    users.forEach(user -> System.out.println(user));
} 
notIn 

不在值列表中

@Test
void testNoIn(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.notIn("id",1,2);
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (id NOT IN (?,?))
    users.forEach(user -> System.out.println(user));
}
inSql

使用子查询

@Test
void testIsSql(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.inSql("age", "select age from user where id = 1");
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (age IN (select age from user where id = 1))
    users.forEach(user -> System.out.println(user));
}
notInSql

使用子查询

​@Test
void testNotIsSql(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.notInSql("age", "select age from user where id = 1");
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (age Not IN (select age from user where id = 1))
    users.forEach(user -> System.out.println(user));
}
groupBy

分组

@Test
void testGroupBy(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.select("age, count(*) numbers"); // SELECT age, count(*) numbers
    qw.groupBy("age");
    List users = userMapper.selectList(qw);
    // SELECT age, count(*) numbers FROM user GROUP BY age
    users.forEach(user -> System.out.println("查询结果:"+user));
}
orderByAsc

按字段升序

@Test
void testOrderByAsc(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.orderByAsc("name","age");
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user ORDER BY name ASC,age ASC
    users.forEach(user -> System.out.println("查询结果:"+user));
}
orderByDesc

按字段降序

@Test
void testOrderByDesc(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.orderByDesc("name","age");
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user ORDER BY name DESC,age DESC
    users.forEach(user -> System.out.println("查询结果:"+user));
}
order

指定字段和判断方法

orderBy(boolean condition, boolean isAsc, R column) {}

解析:

condition : 条件是否加入到 SQL语句的后面

  • true:表示加入到SQL语句后面

SELECt id,name,age FROM user ORDER BY age ASC
  • false:表示不加入sql语句的后面

SELECt id,name,age FROM user ORDER BY age ASC

isAsc:条件是否是升序排序

  • true:表示升序排序

SELECt id,name,age FROM user ORDER BY age ASC
  • false:表示降序排序

SELECt id,name,age FROM user ORDER BY age DESC
@Test
void testOrder(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.orderBy(true,true,"age");
    List users = userMapper.selectList(qw);
    users.forEach(user -> System.out.println("查询结果:"+user));
}

可以使用链式编程的方式,实现多条件排序

@Test
void testOrder2(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.orderBy(true,true,"age")
            .orderBy(true,false,"name");
    List users = userMapper.selectList(qw);
    // age asc, name desc
    // SELECT id,name,age FROM user ORDER BY age ASC,name DESC
    users.forEach(user -> System.out.println("查询结果:"+user));
}
and, or

条件连接作用,默认是and

@Test
void testOr(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.eq("name","zhangsan")
            .or()
            .eq("age",22);
    List users = userMapper.selectList(qw);
    // ELECT id,name,age FROM user WHERe (name = ? OR age = ?)
    users.forEach(user -> System.out.println("查询结果:"+user));
}
last

拼接SQL语句到MP的SQL语句的结尾

@Test
void testLast(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.eq("name","zhangsan")
            .or()
            .eq("age",22)
            .last("limit 1");
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (name = ? OR age = ?) limit 1
    users.forEach(user -> System.out.println("查询结果:"+ user));
}
exists

判断条件,拼接 EXISTS(sql语句)

@Test
void testExists(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.exists("select id from user where age > 20");
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (EXISTS (select id from user where age > 20))
    users.forEach(user -> System.out.println("查询结果:"+user));
}
notExists

与exists *** 作相反

@Test
void testNotExists(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.notExists("select id from user where age > 20");
    List users = userMapper.selectList(qw);
    // SELECT id,name,age FROM user WHERe (NOT EXISTS (select id from user where age > 20))
    users.forEach(user -> System.out.println("查询结果:"+user));
}
分页查询

需要配置一个配置类

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

这里使用的是mysql数据库,DbType.MYSQL。

需要扫描Mapper包

@MapperScan("com.km.mybatis_plus.mapper")

简单测试

@Test
void testPage(){
    QueryWrapper qw = new QueryWrapper<>();
    qw.gt("age","15");
    IPage page = new Page<>();
    page.setCurrent(2); //第一页
    page.setSize(3); // 设置每页记录条数
    // 还可以设置其他参数
    IPage userPage = userMapper.selectPage(page, qw);
    // 获取分页后的记录
    List users = userPage.getRecords();
    for (User user : users){
        System.out.println("查询:"+user);
    }
}

【底层分页步骤】,以上面案例为例

1.统计符合条件的记录条数

SELECT COUNT(*) AS total FROM user WHERe (age > ?)

2.实现分页,在sql语句结尾加上 limit ?,?

SELECt id,name,age FROM user WHERe (age > ?) LIMIT ?,?

注意:如果是显示第一页,limit后面只有一个占位符。

Page类的一些默认配置

public Page() {
    this.records = Collections.emptyList();
    this.total = 0L;
    this.size = 10L;
    this.current = 1L;
    this.orders = new ArrayList();
    this.optimizeCountSql = true;
    this.searchCount = true;
    this.optimizeJoinOfCountSql = true;
}
MP代码生成器

AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

MyBatis-Plus 从 3.0.3 之后移除了代码生成器与模板引擎的默认依赖,需要手动添加相关依赖:


    com.baomidou
    mybatis-plus-generator
    3.4.1

    org.apache.velocity
    velocity-engine-core
    2.3

上面的模板引擎,是MyBatis-plus默认支持的,还有一些其他模板引擎,如:Freemarker、Beetl,用户可以选择自己熟悉的模板引擎,如果都不满足您的要求,可以采用自定义模板引擎。

Freemarker模板依赖


    org.freemarker
    freemarker
    latest-freemarker-version

Beetl模板依赖


    com.ibeetl
    beetl
    latest-beetl-version

注意!如果您选择了非默认引擎,需要在 AutoGenerator 中 设置模板引擎。

AutoGenerator generator = new AutoGenerator();
​
// set freemarker engine
generator.setTemplateEngine(new FreemarkerTemplateEngine());
​
// set beetl engine
generator.setTemplateEngine(new BeetlTemplateEngine());
​
// set custom engine (reference class is your custom engine class)
generator.setTemplateEngine(new CustomTemplateEngine());
​
// other config

创建AutoMapper类,用来生成代码

// 代码生成器
public class AutoMapper {
    public static void main(String[] args) {
        // 创建AutoGenerator, MP中的对象
        AutoGenerator autoGenerator = new AutoGenerator();
        // 设置全局变量
        // 设置数据源DataSource
        // 设置Package信息
        // 设置策略
        // 执行代码生成
        autoGenerator.execute();
    }
}

设置全局变量

// 设置全局变量
GlobalConfig globalConfig = new GlobalConfig();
// 设置代码生成的位置,磁盘的位置
globalConfig.setOutputDir(System.getProperty("user.dir")+"/src/main/java");
// 设置生成Mapper的名称
globalConfig.setMapperName("%sMapper"); // 例如:UserMapper,都是以Mapper结尾
// 设置生成Service接口的名称
globalConfig.setServiceName("%sService"); // 例如:UserService
// 设置生成Service实现类的名称
globalConfig.setServiceImplName("%sServiceImpl"); // 例如:UserServiceImpl
// 设置生成Controller类的名称
globalConfig.setControllerName("%sController"); // UserController
// 设置作者
globalConfig.setAuthor("123");
// 配置主键ID类型
globalConfig.setIdType(IdType.AUTO);
// 将GlobalConfig配置加入AutoGenerator
autoGenerator.setGlobalConfig(globalConfig);

设置数据源DataSource

// 设置数据源DataSource
DataSourceConfig dataSourceConfig = new DataSourceConfig();
// 设置驱动
dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
// 设置url
dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/数据库名?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false&&nullCatalogMeansCurrent=true");
// 设置数据库的用户名
dataSourceConfig.setUsername("账号");
// 设置密码
dataSourceConfig.setPassword("密码");
// 将DataSourceConfig配置加入AutoGenerator
autoGenerator.setDataSource(dataSourceConfig);

设置Package信息

// 设置Package信息
PackageConfig packageConfig = new PackageConfig();
// 设置模块名,相当于包名
packageConfig.setModuleName("auto");
// 设置父包名
packageConfig.setParent("com.km"); // com.km.auto
// 将PackageConfig配置加入AutoGenerator
autoGenerator.setPackageInfo(packageConfig);

设置策略

// 设置策略
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setNaming(NamingStrategy.underline_to_camel);
// 设置支持驼峰命名
strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
// 将StrategyConfig配置加入AutoGenerator
autoGenerator.setStrategy(strategyConfig);

附加代码生成器执行目录

 

简单测试

@SpringBootTest
class MybatisPlusAutoTests {
​
    @Resource
    private UserMapper userMapper;
​
    @Test
    void testAuto(){
        User user = new User();
        user.setAge(55);
        user.setName("张三");
        int insert = userMapper.insert(user);
        System.out.println("结果:"+insert);
    }
}

可以去官网查看其他信息:连接

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5612444.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)