当前位置:   article > 正文

mybatis-plus超详细笔记_mybatisplus笔记

mybatisplus笔记

目录

前言

在学习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的解决方法

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

先创建一个项目
在这里插入图片描述
在代码中创建连接数据库的配置文件

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

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

  1. <!-- mybatis-plus -->
  2. <dependency>
  3. <groupId>com.baomidou</groupId>
  4. <artifactId>mybatis-plus-boot-starter</artifactId>
  5. <version>3.0.5</version>
  6. </dependency>

以及数据库的依赖文件

  1. <dependency>
  2. <groupId>mysql</groupId>
  3. <artifactId>mysql-connector-java</artifactId>
  4. <scope>runtime</scope>
  5. <version>5.1.6</version>
  6. </dependency>

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

1.2 项目构建

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

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

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

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

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

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

  1. public interface UserMapper extends BaseMapper<User> {
  2. }

具体BaseMapper类的定义源码如下
在这里插入图片描述
主要是这个框架中的对象,定义17个操作方法(CRUD)

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

  1. @SpringBootApplication
  2. @MapperScan(value = "com.wkcto.plus.mapper")
  3. public class PlusApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run(PlusApplication.class, args);
  6. }
  7. }

测试文件

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

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

  1. @SuppressWarnings("all")
  2. @RunWith(SpringRunner.class)
  3. @SpringBootTest
  4. public class UserTest {
  5. //定义StudentMapper
  6. @Autowired
  7. private UserMapper userDao;
  8. @Test
  9. public void testInsertStudent() {
  10. User user = new User();
  11. user.setName("zs");
  12. user.setEmail("zd.com");
  13. user.setAge(20);
  14. int rows = userDao.insert(user);
  15. System.out.println("inserStudent rows:" + rows);
  16. }
  17. }

2. 配置日志

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

主要在yml配置
具体信息为

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

3. CURD基本用法

完整代码就不书写了,只写核心代码
在这里插入图片描述

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

3.1 插入操作

  1. //添加数据后,获取主键值
  2. @Test
  3. public void testInsertGetId(){
  4. User user = new User();
  5. user.setName("李四");
  6. user.setAge(20);
  7. user.setEmail("lisi@163.com");
  8. int rows = userDao.insert(user);
  9. System.out.println("insert user rows:"+rows);
  10. //获取主键id ,刚添加数据库中的数据的id
  11. int id = user.getId();//主键字段对应的get方法
  12. System.out.println("主键id:"+id);
  13. }

3.2 更新操作

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

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

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

3.3 删除操作

  • 按主键删除一条数据
    方法是deleteById()
  1. @Test
  2. public void testDeleteById(){
  3. //DELETE FROM user WHERE id=?
  4. int rows = userDao.deleteById(3);
  5. System.out.println("deleteById:"+rows);
  6. }
  • 按条件删除数据, 条件是封装到Map对象中
    方法是deleteByMap(map对象);
  1. @Test
  2. public void testDeleteByMap(){
  3. //创建Map对象,保存条件值
  4. Map<String,Object> map = new HashMap<>();
  5. //put("表的字段名",条件值) , 可以封装多个条件
  6. map.put("name","zs");
  7. map.put("age",20);
  8. //调用删除方法
  9. //DELETE FROM user WHERE name = ? AND age = ?
  10. int rows = userDao.deleteByMap(map);
  11. System.out.println("deleteByMap rows:"+rows);
  12. }
  • 使用多个主键值,删除数据
    使用列表,方法是deleteBatchIds()

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

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

3.4 查询操作

  • 根据主键值查询,方法是selectById
  1. @Test
  2. public void testSelectById(){
  3. /**
  4. * 生成的sql: SELECT id,name,email,age FROM user WHERE id=?
  5. * 如果根据主键没有查找到数据, 得到的返回值是 null
  6. */
  7. User user = userDao.selectById(6);
  8. System.out.println("selectById:"+user);
  9. //在使用对象之前,需要判断对象是否为null
  10. if(user != null){
  11. //业务方法的调用
  12. }
  13. }
  • 实现批处理查询,根据多个主键值查询, 获取到List
    方法是selectBatchIds
  1. @Test
  2. public void testSelectBatchId(){
  3. List<Integer> ids = new ArrayList<>();
  4. ids.add(6);
  5. ids.add(9);
  6. ids.add(10);
  7. //查询数据
  8. //SELECT id,name,email,age FROM user WHERE id IN ( ? , ? , ? )
  9. List<User> users = userDao.selectBatchIds(ids);
  10. System.out.println("size:"+users.size());
  11. for (User u:users){
  12. System.out.println("查询的用户:"+u);
  13. }
  14. }

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

List<Integer> ids = Stream.of(6, 9, 10, 15).collect(Collectors.toList());
  • 使用Map做多条件查询
    方法是selectByMap()
  1. @Test
  2. public void testSelectMap(){
  3. //创建Map,封装查询条件
  4. Map<String,Object> map = new HashMap<>();
  5. //key是字段名, value:字段值 ,多个key,是and 联接
  6. map.put("name","zhangsan");
  7. map.put("age",20);
  8. //根据Map查询
  9. //SELECT id,name,email,age FROM user WHERE name = ? AND age = ?
  10. List<User> users = userDao.selectByMap(map);
  11. users.forEach(user -> {
  12. System.out.println("selectByMap:"+user);
  13. });
  14. }

4. ActiveRecord

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

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

主要的区别在于

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

查看model类中的源码
在这里插入图片描述

和原先步骤一样

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

使用AR,要求实体类需要继承MP中的Model,Model中提供了对数据库的CRUD的操作
在这里插入图片描述
mapper文件也要书写一下
因为DeptMapper是不需要使用的,MP需要使用DeptMapper获取到数据库的表的信息。
如果不定义DeptMapper, MP会报错, 找不到表的定义信息

  1. public interface DeptMapper extends BaseMapper<Dept> {
  2. }

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

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

具体测试类如下

4.1 插入操作

调用的是model中的insert方法

  1. @Test
  2. public void testARInsert(){
  3. //定义dept的实体
  4. Dept dept = new Dept();
  5. dept.setName("行政部");
  6. dept.setMobile("010-66666666");
  7. dept.setManager(5);
  8. //调用实体对象自己的方法,完成对象自身到数据库的添加操作
  9. boolean flag = dept.insert();
  10. System.out.println("ar insert result:"+flag);
  11. }

4.2 更新操作

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

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

  1. @Test
  2. public void testARUpdate2(){
  3. //定义实体Dept
  4. Dept dept = new Dept();
  5. // dept.setId(1);
  6. dept.setMobile("010-3333333");
  7. //name , manager是没有修改的
  8. //根据主键id更新记录
  9. // UPDATE dept SET name=?, mobile=?, manager=? WHERE id=? // id = 1
  10. // null的属性值不做更新处理,在update中没有null的字段
  11. //UPDATE dept SET mobile=? WHERE id=?
  12. boolean result = dept.updateById();//使用dept实体主键的值,作为where id = 1
  13. System.out.println("ar updateById result:"+result);
  14. }

4.3 删除操作

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

4.4 查询操作

方法selectByID

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

5. 表和列

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

5.1 主键类型

IdType的枚举类型如下

  1. public enum IdType {
  2. AUTO(0),
  3. NONE(1),
  4. INPUT(2),
  5. ID_WORKER(3),
  6. UUID(4),
  7. ID_WORKER_STR(5);
  8. private int key;
  9. private IdType(int key) {
  10. this.key = key;
  11. }
  12. public int getKey() {
  13. return this.key;
  14. }
  15. }
  • 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文件的继承

  1. public interface StudentMapper extends BaseMapper<Student> {
  2. //自定义方法
  3. public int insertStudent(Student student);
  4. public Student selectStudentById(Integer id);
  5. public List<Student> selectByName(String name);
  6. }

方法的定义在resources文件下

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.wkcto.plus.mapper.StudentMapper">
  6. <insert id="insertStudent">
  7. insert into student(name,age,email,status) values(#{name},#{age},#{email},#{status})
  8. </insert>
  9. <select id="selectStudentById" resultType="com.wkcto.plus.entity.Student">
  10. select id,name,age,email,status from student where id=#{studentId}
  11. </select>
  12. <select id="selectByName" resultType="com.wkcto.plus.entity.Student">
  13. select id,name,age,email,status from student where name=#{name}
  14. </select>
  15. </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
查询全部

  1. @Test
  2. public void testAllEq() {
  3. QueryWrapper<Student> qw = new QueryWrapper<>();
  4. //组装条件
  5. Map<String, Object> param = new HashMap<>();
  6. //map<key,value> key列名 , value:查询的值
  7. param.put("name", "张三");
  8. param.put("age", 22);
  9. param.put("status", 1);
  10. qw.allEq(param);
  11. //调用MP自己的查询方法
  12. //SELECT id,name,age,email,status FROM student WHERE name = ? AND age = ?
  13. //WHERE name = ? AND age = ? AND status = ?
  14. List<Student> students = studentDao.selectList(qw);
  15. students.forEach(stu -> System.out.println(stu));
  16. }

如果有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 条件

符号判断

  1. //eq("列名",值) 等于
  2. @Test
  3. public void testEq() {
  4. QueryWrapper<Student> qw = new QueryWrapper<>();
  5. //组成条件
  6. qw.eq("name", "李四");
  7. //WHERE name = ?
  8. List<Student> students = studentDao.selectList(qw);
  9. students.forEach(stu -> System.out.println("查询eq:" + stu));
  10. }
  11. //ne不等于
  12. @Test
  13. public void testNe() {
  14. QueryWrapper<Student> qw = new QueryWrapper<>();
  15. //组成条件
  16. qw.ne("name", "张三");
  17. // WHERE name <> ?
  18. List<Student> students = studentDao.selectList(qw);
  19. students.forEach(stu -> System.out.println("查询ne:" + stu));
  20. }
  21. //gt 大于
  22. @Test
  23. public void testGt() {
  24. QueryWrapper<Student> qw = new QueryWrapper<>();
  25. qw.gt("age", 30); //age > 30
  26. // WHERE age > ?
  27. List<Student> students = studentDao.selectList(qw);
  28. students.forEach(stu -> System.out.println("stu:" + stu));
  29. }
  30. //ge 大于等于
  31. @Test
  32. public void testGe() {
  33. QueryWrapper<Student> qw = new QueryWrapper<>();
  34. qw.ge("age", 31);// >=31
  35. //WHERE age >= ?
  36. List<Student> students = studentDao.selectList(qw);
  37. students.forEach(stu -> System.out.println("student:" + stu));
  38. }
  39. //lt 小于
  40. @Test
  41. public void testLt() {
  42. QueryWrapper<Student> qw = new QueryWrapper<>();
  43. qw.lt("age", 32);
  44. // WHERE age < ?
  45. List<Student> students = studentDao.selectList(qw);
  46. students.forEach(stu -> System.out.println("student:" + stu));
  47. }
  48. //le 小于等于
  49. @Test
  50. public void testLe() {
  51. QueryWrapper<Student> qw = new QueryWrapper<>();
  52. qw.le("age", 32);
  53. // WHERE age <= ?
  54. List<Student> students = studentDao.selectList(qw);
  55. students.forEach(stu -> System.out.println("student:" + stu));
  56. }

区间范围内

  1. //介值
  2. @Test
  3. public void testBetween() {
  4. QueryWrapper<Student> qw = new QueryWrapper<>();
  5. //between("列名",开始值,结束值)
  6. qw.between("age", 22, 28);
  7. // where age >= 12 and age < 28
  8. List<Student> students = studentDao.selectList(qw);
  9. students.forEach(stu -> System.out.println(stu));
  10. }
  11. //不在介值
  12. @Test
  13. public void testNotBetween() {
  14. QueryWrapper<Student> qw = new QueryWrapper<>();
  15. qw.notBetween("age", 18, 28);
  16. //WHERE age NOT BETWEEN ? AND ?
  17. // where age < 18 or age > 28
  18. List<Student> students = studentDao.selectList(qw);
  19. students.forEach(stu -> System.out.println(stu));
  20. }

匹配字段

  1. /**
  2. * like 匹配某个值
  3. */
  4. @Test
  5. public void testLike() {
  6. QueryWrapper<Student> qw = new QueryWrapper<>();
  7. qw.like("name", "张");
  8. // WHERE name LIKE %张%
  9. List<Student> students = studentDao.selectList(qw);
  10. students.forEach(stu -> System.out.println(stu));
  11. }
  12. /**
  13. * notLike 不匹配某个值
  14. */
  15. @Test
  16. public void testNotLike() {
  17. QueryWrapper<Student> qw = new QueryWrapper<>();
  18. qw.notLike("name", "张");
  19. // WHERE name NOT LIKE ? %张%
  20. List<Student> students = studentDao.selectList(qw);
  21. students.forEach(stu -> System.out.println(stu));
  22. }
  23. /**
  24. * likeLeft "%值"
  25. */
  26. @Test
  27. public void testLikeLeft() {
  28. QueryWrapper<Student> qw = new QueryWrapper<>();
  29. qw.likeLeft("name", "张");
  30. //WHERE name LIKE %张
  31. List<Student> students = studentDao.selectList(qw);
  32. students.forEach(student -> System.out.println(student));
  33. }
  34. /**
  35. * likeRight "%值"
  36. */
  37. @Test
  38. public void testLikeRight() {
  39. QueryWrapper<Student> qw = new QueryWrapper<>();
  40. qw.likeRight("name", "李");
  41. //WHERE name LIKE 李%
  42. List<Student> students = studentDao.selectList(qw);
  43. students.forEach(student -> System.out.println(student));
  44. }
  45. /**
  46. * isNull , 判断字段是 null
  47. */
  48. @Test
  49. public void testIsNull(){
  50. QueryWrapper<Student> qw = new QueryWrapper<>();
  51. //判断email is null
  52. //WHERE email IS NULL
  53. qw.isNull("email");
  54. print(qw);
  55. }
  56. /**
  57. * isNotNull , 判断字段是 is not null
  58. */
  59. @Test
  60. public void testIsNotNull(){
  61. QueryWrapper<Student> qw = new QueryWrapper<>();
  62. // WHERE email IS NOT NULL
  63. qw.isNotNull("email");
  64. print(qw);
  65. }
  66. private void print(QueryWrapper qw){
  67. List<Student> students = studentDao.selectList(qw);
  68. students.forEach(student -> System.out.println(student));
  69. }

in 或者子查询

  1. /**
  2. * isNull , 判断字段是 null
  3. */
  4. @Test
  5. public void testIsNull(){
  6. QueryWrapper<Student> qw = new QueryWrapper<>();
  7. //判断email is null
  8. //WHERE email IS NULL
  9. qw.isNull("email");
  10. print(qw);
  11. }
  12. /**
  13. * isNotNull , 判断字段是 is not null
  14. */
  15. @Test
  16. public void testIsNotNull(){
  17. QueryWrapper<Student> qw = new QueryWrapper<>();
  18. // WHERE email IS NOT NULL
  19. qw.isNotNull("email");
  20. print(qw);
  21. }
  22. /**
  23. * in 值列表
  24. */
  25. @Test
  26. public void testIn(){
  27. QueryWrapper<Student> qw = new QueryWrapper<>();
  28. //in(列名,多个值的列表)
  29. //WHERE name IN (?,?,?)
  30. qw.in("name","张三","李四","周丽");
  31. print(qw);
  32. }
  33. /**
  34. * notIn 不在值列表
  35. */
  36. @Test
  37. public void testNoIn(){
  38. QueryWrapper<Student> qw = new QueryWrapper<>();
  39. //in(列名,多个值的列表)
  40. //WHERE name NOT IN (?,?,?)
  41. qw.notIn("name","张三","李四","周丽");
  42. print(qw);
  43. }
  44. /**
  45. * in 值列表
  46. */
  47. @Test
  48. public void testIn2(){
  49. QueryWrapper<Student> qw = new QueryWrapper<>();
  50. List<Object> list = new ArrayList<>();
  51. list.add(1);
  52. list.add(2);
  53. //WHERE status IN (?,?)
  54. qw.in("status",list);
  55. print(qw);
  56. }
  57. /**
  58. * inSql() : 使用子查询
  59. */
  60. @Test
  61. public void testInSQL(){
  62. QueryWrapper<Student> qw = new QueryWrapper<>();
  63. //WHERE age IN (select age from student where id=1)
  64. qw.inSql("age","select age from student where id=1");
  65. print(qw);
  66. }
  67. /**
  68. * notInSql() : 使用子查询
  69. */
  70. @Test
  71. public void testNotInSQL(){
  72. QueryWrapper<Student> qw = new QueryWrapper<>();
  73. //WHERE age NOT IN (select age from student where id=1)
  74. qw.notInSql("age","select age from student where id=1");
  75. print(qw);
  76. }
  77. private void print(QueryWrapper qw){
  78. List<Student> students = studentDao.selectList(qw);
  79. students.forEach(student -> System.out.println(student));
  80. }

分组

  1. /**
  2. * groupBy:分组
  3. */
  4. @Test
  5. public void testGroupby(){
  6. QueryWrapper<Student> qw = new QueryWrapper<>();
  7. qw.select("name,count(*) personNumbers");//select name,count(*) personNumbers
  8. qw.groupBy("name");
  9. // SELECT name,count(*) personNumbers FROM student GROUP BY name
  10. print(qw);
  11. }

字段升序降序

  1. /**
  2. * orderbyAsc : 按字段升序
  3. */
  4. @Test
  5. public void testOrderByAsc(){
  6. QueryWrapper<Student> qw= new QueryWrapper<>();
  7. //FROM student ORDER BY name ASC , age ASC
  8. qw.orderByAsc("name","age");
  9. print(qw);
  10. }
  11. /**
  12. * orderbyDesc : 按字段降序
  13. */
  14. @Test
  15. public void testOrderByDesc(){
  16. QueryWrapper<Student> qw= new QueryWrapper<>();
  17. // ORDER BY name DESC , id DESC
  18. qw.orderByDesc("name","id");
  19. print(qw);
  20. }
  21. /**
  22. * order :指定字段和排序方向
  23. *
  24. * boolean condition : 条件内容是否加入到 sql语句的后面。
  25. * true:条件加入到sql语句
  26. * FROM student ORDER BY name ASC
  27. *
  28. * false:条件不加入到sql语句
  29. * FROM student
  30. */
  31. @Test
  32. public void testOrder(){
  33. QueryWrapper<Student> qw = new QueryWrapper<>();
  34. qw.orderBy(true,true,"name")
  35. .orderBy(true,false,"age")
  36. .orderBy(true,false,"email");
  37. // name asc, age desc , email desc
  38. //FROM student ORDER BY name ASC , age DESC , email DESC
  39. print(qw);
  40. }

拼接以及存在与否

  1. /**
  2. * and ,or方法
  3. */
  4. @Test
  5. public void testOr(){
  6. QueryWrapper<Student> qw= new QueryWrapper<>();
  7. //WHERE name = ? OR age = ?
  8. qw.eq("name","张三")
  9. .or()
  10. .eq("age",22);
  11. print(qw);
  12. }
  13. /**
  14. * last : 拼接sql语句到MP的sql语句的最后
  15. */
  16. @Test
  17. public void testLast(){
  18. QueryWrapper<Student> qw = new QueryWrapper<>();
  19. //SELECT id,name,age,email,status FROM student WHERE name = ? OR age = ? limit 1
  20. qw.eq("name","张三")
  21. .or()
  22. .eq("age",22)
  23. .last("limit 1");
  24. print(qw);
  25. }
  26. /**
  27. * exists : 判断条件
  28. *
  29. * notExists
  30. */
  31. @Test
  32. public void testExists(){
  33. QueryWrapper<Student> qw= new QueryWrapper<>();
  34. //SELECT id,name,age,email,status FROM student
  35. // WHERE EXISTS (select id from student where age > 20)
  36. //qw.exists("select id from student where age > 90");
  37. //SELECT id,name,age,email,status FROM student WHERE
  38. // NOT EXISTS (select id from student where age > 90)
  39. qw.notExists("select id from student where age > 90");
  40. print(qw);
  41. }

7.2 分页

  1. /**
  2. * 分页:
  3. * 1.统计记录数,使用count(1)
  4. * SELECT COUNT(1) FROM student WHERE age > ?
  5. * 2.实现分页,在sql语句的末尾加入 limit 0,3
  6. * SELECT id,name,age,email,status FROM student WHERE age > ? LIMIT 0,3
  7. */
  8. @Test
  9. public void testPage(){
  10. QueryWrapper<Student> qw = new QueryWrapper<>();
  11. qw.gt("age",22);
  12. IPage<Student> page = new Page<>();
  13. //设置分页的数据
  14. page.setCurrent(1);//第一页
  15. page.setSize(3);// 每页的记录数
  16. IPage<Student> result = studentDao.selectPage(page,qw);
  17. //获取分页后的记录
  18. List<Student> students = result.getRecords();
  19. System.out.println("students.size()="+students.size());
  20. //分页的信息
  21. long pages = result.getPages();
  22. System.out.println("页数:"+pages);
  23. System.out.println("总记录数:"+result.getTotal());
  24. System.out.println("当前页码:"+result.getCurrent());
  25. System.out.println("每页的记录数:"+result.getSize());
  26. }

8. 代码生成器

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

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

添加依赖包

  1. <!-- 模板引擎 -->
  2. <dependency>
  3. <groupId>org.apache.velocity</groupId>
  4. <artifactId>velocity-engine-core</artifactId>
  5. <version>2.0</version>
  6. </dependency>

创建一个生成类

  1. public class AutoMapper {
  2. public static void main(String[] args) {
  3. //创建AutoGenerator ,MP中对象
  4. AutoGenerator ag = new AutoGenerator();
  5. //设置全局配置
  6. GlobalConfig gc = new GlobalConfig();
  7. //设置代码的生成位置, 磁盘的目录
  8. String path = System.getProperty("user.dir");
  9. gc.setOutputDir(path+"/src/main/java");
  10. //设置生成的类的名称(命名规则)
  11. gc.setMapperName("%sMapper");//所有的Dao类都是Mapper结尾的,例如DeptMapper
  12. //设置Service接口的命名
  13. gc.setServiceName("%sService");//DeptService
  14. //设置Service实现类的名称
  15. gc.setServiceImplName("%sServiceImpl");//DeptServiceImpl
  16. //设置Controller类的命名
  17. gc.setControllerName("%sController");//DeptController
  18. //设置作者
  19. gc.setAuthor("码农研究僧");
  20. //设置主键id的配置
  21. gc.setIdType(IdType.ID_WORKER);
  22. ag.setGlobalConfig(gc);
  23. //设置数据源DataSource
  24. DataSourceConfig ds = new DataSourceConfig();
  25. //驱动
  26. ds.setDriverName("com.mysql.jdbc.Driver");
  27. //设置url
  28. ds.setUrl("jdbc:mysql://localhost:3306/springdb");
  29. //设置数据库的用户名
  30. ds.setUsername("root");
  31. //设置密码
  32. ds.setPassword("123456");
  33. //把DataSourceConfig赋值给AutoGenerator
  34. ag.setDataSource(ds);
  35. //设置Package信息
  36. PackageConfig pc = new PackageConfig();
  37. //设置模块名称, 相当于包名, 在这个包的下面有 mapper, service, controller。
  38. pc.setModuleName("order");
  39. //设置父包名,order就在父包的下面生成
  40. pc.setParent("com.wkcto"); //com.wkcto.order
  41. ag.setPackageInfo(pc);
  42. //设置策略
  43. StrategyConfig sc = new StrategyConfig();
  44. sc.setNaming(NamingStrategy.underline_to_camel);
  45. //设置支持驼峰的命名规则
  46. sc.setColumnNaming(NamingStrategy.underline_to_camel);
  47. ag.setStrategy(sc);
  48. //执行代码的生成
  49. ag.execute();
  50. }
  51. }

还要配置一个配置类

  1. @Configuration
  2. public class Config {
  3. /***
  4. * 定义方法,返回的返回值是java 对象,这个对象是放入到spring容器中
  5. * 使用@Bean修饰方法
  6. * @Bean等同于<bean></bean>
  7. */
  8. @Bean
  9. public PaginationInterceptor paginationInterceptor(){
  10. return new PaginationInterceptor();
  11. }
  12. }

点击运行就会生成代码文件
在这里插入图片描述
执行测试类

  1. @SuppressWarnings("all")
  2. @RunWith(SpringRunner.class)
  3. @SpringBootTest
  4. public class StudentMapperTest {
  5. //注入生成的StudentMapper
  6. @Autowired
  7. StudentMapper studentMapper;
  8. @Test
  9. public void testInsertStudent(){
  10. Student student = new Student();
  11. student.setName("john");
  12. student.setAge(28);
  13. student.setEmail("john@yahu.com");
  14. student.setStatus(2);
  15. int rows = studentMapper.insert(student);
  16. System.out.println("insert Student rows:"+rows);
  17. }
  18. @Test
  19. public void testSelect(){
  20. Student student = studentMapper.selectById(1);
  21. System.out.println("testSelect:"+student);
  22. }
  23. @Test
  24. public void testSelect1(){
  25. QueryWrapper<Student> qw = new QueryWrapper<>();
  26. qw.gt("age",35);
  27. //selectOne:查询结果只能是一条记录或没有没有记录,多条记录是报错的
  28. Student student = studentMapper.selectOne(qw);
  29. System.out.println("testSelect:"+student);
  30. }
  31. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/756178
推荐阅读