mybatisPlus官方教程学习记录

99 阅读6分钟

一、基本使用

1、常用注解

@tableName

这个注解的作用就是当数据库中的表名和实体类的类名不一致的时候,加上这个注解将这个表和实体类联系起来,操作数据库的时候就不会报错。

@Data
@TableName("t_user")
public class User {

    //主键id
    private Long id;
    //姓名
    private String name;
    //年龄
    private int age;
    //邮箱
    private String email;
    //上司id
    private Long managerId;
    //创建时间
    private LocalDateTime createTime;

}

@tableId

这个注解的作用是当表中主键和实体类中代表主键的字段名不一样时,使用该注解标注联系起来二者。

@Data
@TableName("t_user")
public class User {

    //主键id
    @TableId("t_id")
    private Long id;
    //姓名
    private String name;
    //年龄
    private int age;
    //邮箱
    private String email;
    //上司id
    private Long managerId;
    //创建时间
    private LocalDateTime createTime;

}

@TableField

  1. 当实体类中的普通字段和数据表中的列名不一样的时候使用该注解进行标记。
  2. 排除实体类中的非表字段,下面有展示。
@Data
@TableName("t_user")
public class User {

    //主键id
    @TableId("t_id")
    private Long id;
    //姓名
    @TableField("realName")
    private String name;
    //年龄
    private int age;
    //邮箱
    private String email;
    //上司id
    private Long managerId;
    //创建时间
    private LocalDateTime createTime;

}

2、排除非表字段的三种方式

  1. 在字段前面加入 transient 关键字,缺点就是不能序列化。
  2. 在字段前加入 static 关键字,生成相应的get set 方法,也有缺点。
  3. 推荐使用 @tableField(exist = false)
@Data
@TableName("t_user")
public class User {

    //主键id
    private Long id;
    //姓名
    @TableField("realName")
    private String name;
    //年龄
    private int age;
    //邮箱
    private String email;
    //上司id
    private Long managerId;
    //创建时间
    private LocalDateTime createTime;
    //备注
    @TableField(exist = false)
    private String remark;

}

二、mp查询方法

1、普通查询

  1. selectById() 根据id查询一条数据,没啥要说的。
@Test
public void selectTest(){
    User user = userMapper.selectById(1087982257332887553L);
    System.out.println(user);
}
  1. selectBatchIds() 查询多条数据
@Test
public void selectBatchIdsTest(){
    List<Long> ids = Arrays.asList(1088248166370832385L, 1088250446457389058L, 1543507560599302145L);
    List<User> users = userMapper.selectBatchIds(ids);
    users.forEach(System.out::println);
}
  1. selectByMap() 参数是一个map,返回一个集合
@Test
public void selectByMapTest(){
    /*
    map.put("name",小明);
    map.put("age",12);
    select * from table_name where name = '小明' and age = 12;
     */
    HashMap<String, Object> map = new HashMap<>();
    map.put("name", "张三");
    map.put("age",27);
    List<User> users = userMapper.selectByMap(map);
    for (User user : users) {
        System.out.println(user);
    }
}

DEBUG==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE name = ? AND age = ?
DEBUG==> Parameters: 张三(String), 27(Integer)

2、条件构造器查询

  1. selectList()
/**
 * 根据条件构造器查询
 */
@Test
public void selectByWrapper(){
    /*
    1.名字中含有 '张'
    2.年龄小于 30
     */
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    /**
     * 链式调用
     */
    QueryWrapper<User> wrapper = queryWrapper.like("name", "张").lt("age", 30);
    List<User> users = userMapper.selectList(queryWrapper);
    for (User user : users) {
        System.out.println(user);
    }
    
    
DEBUG==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (name LIKE ? AND age < ?)
DEBUG==> Parameters: %%(String), 30(Integer)
/**
 * 根据条件构造器查询
 */
@Test
public void selectByWrapper2(){
    /*
      名字中含有雨,年龄大于20,小于40,邮箱非空

     */
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.like("name", "雨").between("age", 20, 40).isNotNull("email");
    List<User> users = userMapper.selectList(queryWrapper);
    for (User user : users) {
        System.out.println(user);
    }
}


DEBUG==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (name LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
DEBUG==> Parameters: %%(String), 20(Integer), 40(Integer)
/**
 * 根据条件构造器查询
 */
@Test
public void selectByWrapper3(){
    /*
        名字为王姓,或者年龄大于等于25,按照年龄降序排列,年龄相同按照id升序排列
     */
    QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
    userQueryWrapper.like("name","王").or().ge("age",25).orderByDesc("age").orderByAsc("id");
    List<User> users = userMapper.selectList(userQueryWrapper);
    for (User user : users) {
        System.out.println(user);
    }
}

DEBUG==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (name LIKE ? OR age >= ?) ORDER BY age DESC,id ASC
DEBUG==> Parameters: %%(String), 25(Integer)
/**
 * 根据条件构造器查询
 */
@Test
public void selectByWrapper4(){
    /*
      4. 创建日期为2019年2月14日,并且直属上级为名字为王姓
      date_format(create_time, '%Y-%m-%d') and manager_id in (select id from user where name like '王%')
     */
    QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
    userQueryWrapper.apply("date_format(create_time,'%Y-%m-%d')={0}","2019-02-14");
    userQueryWrapper
            .inSql("manager_id","select id from user where name like '王%'");
    List<User> users = userMapper.selectList(userQueryWrapper);
    for (User user : users) {
        System.out.println(user);
    }
    
DEBUG==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (date_format(create_time,'%Y-%m-%d')=? AND manager_id IN (select id from user where name like '王%'))
DEBUG==> Parameters: 2019-02-14(String)

上面例子中apply()可以拼接sql语句,具体看官方文档,apply有两种使用方法,另一种有sql注入的风险。

/**
 * 根据条件构造器查询
 */
@Test
public void selectByWrapper5(){
    /*
    名字为王姓并且(年龄小于40或邮箱为空)
    name = '王%' and (age < 40 or email is not null)
     */
    QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
    userQueryWrapper.likeRight("name","王").and(i -> i.lt("age",40).isNotNull("email"));
    List<User> users = userMapper.selectList(userQueryWrapper);
    for (User user : users) {
        System.out.println(user);
DEBUG==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (name LIKE ? AND (age < ? AND email IS NOT NULL))
DEBUG==> Parameters: 王%(String), 40(Integer)   

3、select不列出全部字段

@Test
public void selectByWrapper8() {
    /*
    年龄为30,31,34,35
    age in (30,31,34,35)
     */
    QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
    userQueryWrapper.select("name","id").in("age", 30,31,34,35);
    List<User> users = userMapper.selectList(userQueryWrapper);
    for (User user : users) {
        System.out.println(user);
    }
}
DEBUG==>  Preparing: SELECT name,id FROM user WHERE (age IN (?,?,?,?))
DEBUG==> Parameters: 30(Integer), 31(Integer), 34(Integer), 35(Integer)

4、condition的作用

条件为空值在sql语句中不会被加到where条件处。

@Test
public void testCondition(){
    String name = "王";
    String email = "";
    condition(name,email);

}

public void condition(String name , String email) {
    QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
    userQueryWrapper.like(StringUtils.isNotEmpty(name),"name",name).gt(StringUtils.isNotEmpty(email),"age",email);
    List<User> users = userMapper.selectList(userQueryWrapper);
    for (User user : users) {
        System.out.println(user);
    }
}


DEBUG==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (name LIKE ?)
DEBUG==> Parameters: %王%(String)

5、实体作为条件构造器构造方法的参数

就是下面这样

 QueryWrapper<User> userQueryWrapper = new QueryWrapper<>(whereUser);

使用的时候可以set设置属性的值,作为查询时列的条件

image.png

@TableField注解可以设置某个字段在查询时是等值查询,还是模糊查询等等

image.png

6、Lambda条件构造器

    /**
     * lambda条件构造器
     *
     * 使用好处就是防止字段名书写错误,Lambda使用  User::getName   , 之前是 name ,name可能会写错
     */
    @Test
    public void selectLambdaTest() {
        //创建Lambda条件构造器的三种方式
//        LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();
//        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<User> lambdaQuery = Wrappers.<User>lambdaQuery();
        lambdaQuery.like(User::getName, "雨");
        List<User> users = userMapper.selectList(lambdaQuery);
        for (User user : users) {
            System.out.println(user);
        }
DEBUG==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (name LIKE ?)
DEBUG==> Parameters: %雨%(String)   

三、自定义sql及分页查询

1、自定义sql

  1. 第一种是在mapper接口层的方法上方使用注解编写sql语句
  2. 第二种是创建mapper层的xml文件在xml文件中写sql语句。需要在springboot配置文件上配置xml文件的location 以上两种方式和mybatis一样相似,也略有差别,具体使用可百度。

2、分页查询

  1. 先写个mybatisPlus配置类,配置分页插件
  2. 之后查询时使用

四、更新方法

1、根据id更新

@Test
public void updateTest(){
    User user = new User();
    user.setId(1543516933342011394L);
    user.setEmail("goudan@qq.com");
    int i = userMapper.updateById(user);
}
DEBUG==>  Preparing: UPDATE user SET age=?, email=? WHERE id=?
DEBUG==> Parameters: 0(Integer), goudan@qq.com(String), 1543516933342011394(Long)
DEBUG<==    Updates: 1

2、 以条件构造器作为参数的更新方法

@Test
public void  updateByWrapperTest(){
    UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
    userUpdateWrapper.eq("name","李艺伟").eq("age",28);
    User user = new User();
    user.setEmail("lyw@qq.com");
    user.setAge(29);
    int update = userMapper.update(user, userUpdateWrapper);
}
DEBUG==>  Preparing: UPDATE user SET age=?, email=? WHERE (name = ? AND age = ?)
DEBUG==> Parameters: 29(Integer), lyw@qq.com(String), 李艺伟(String), 28(Integer)

当只更新少量字段的时候

@Test
public void updateByWrapper3(){
    UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
    userUpdateWrapper.eq("name","李艺伟").set("name","王艺伟").eq("age",29).set("age",30);
    int update = userMapper.update(null, userUpdateWrapper);
}
DEBUG==>  Preparing: UPDATE user SET name=?,age=? WHERE (name = ? AND age = ?)
DEBUG==> Parameters: 王艺伟(String), 30(Integer), 李艺伟(String), 29(Integer)

使用lambda

@Test
public void updateByWrapperLambdaTest(){
    LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
    lambdaUpdateWrapper.eq(User::getName,"王艺伟").set(User::getName,"李艺伟");
    int i = userMapper.update(null, lambdaUpdateWrapper);
}
DEBUG==>  Preparing: UPDATE user SET name=? WHERE (name = ?)
DEBUG==> Parameters: 李艺伟(String), 王艺伟(String)

3、条件构造器中set方法使用

set方法的使用在2中已经使用,就是在更新少量字段的时候

五、删除方法

1、根据id删除的方法

@Test
public void deleteByIdTest(){
    int i = userMapper.deleteById(1543516933342011394L);
    System.out.println("删除条数" + i);
}

2、其他普通删除方法

  1. deleteByMap方法 image.png
  2. deleteBatchIds

image.png

3、以条件构造器为参数的删除方法

使用lambda条件构造器

image.png

六、AR模式、主键策略和基本配置

1、AR模式(active Recode模式)

具体请看

  1. 首先继承Model类
  2. 必须存在对应的原始mapper接口

2、主键策略

生成主键时用的,具体请看 juejin.cn/post/685457…

3、基本配置

官网

七、通用service

image.png