mybatis plus使用

mybatis plus

常见注解

  1. @TableName

    • 作用:指定实体类对应的数据库表名
    • 位置:实体类上
    • 属性:value(指定表名)
  2. @TableId

    • 作用:指定实体类中主键字段对应的数据库表字段
    • 位置:主键字段上
    • 属性:value(指定表字段名),type(指定主键生成策略)
  3. @TableField

    • 作用:指定实体类中非主键字段对应的数据库表字段
    • 位置:非主键字段上
    • 属性:value(指定表字段名)
  4. #IdType

    • 作用:指定主键生成策略
    • 位置:@TableId注解上
    • 属性:value(指定主键生成策略)
类型 核心作用
AUTO 数据库自增(需表主键开启自增,插入时无需赋值)
INPUT 手动输入(插入前必须给主键赋值,否则报错)
ASSIGN_ID 默认策略,雪花算法生成全局唯一的 Long 型主键(无需赋值)
ASSIGN_UUID 生成全局唯一的 UUID 字符串主键(需主键字段为 String 类型)
NONE 无特定策略,跟随 MyBatis-Plus 全局主键配置
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
//假如tb_user是真正的表名,和类名不一样,那么需要对应一下呢
@TableName("tb_user")
public class User {
    // 主键字段也对应一下,并指定主键生成策略为自增,一般主键就是自增的,加了这个之后,插入数据时,主键会自动增长
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    @TableField("username")
    private String username;


    private String password;
    
    private String name;
    
    // 标记非表字段
    @TableField(exist = false)
    private Integer address;
}

总结

  • mybatis plus默认以类名驼峰转下划线作为表名
  • 默认把名为id的字段作为主键
  • 默认把变量名驼峰转下划线作为表的字段名

IService接口

条件查询

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    @Test
    void testQueryWrapper() {

        QueryWrapper<User> wrapper = new QueryWrapper<User>();
        wrapper.select("id", "username","info", "balance")
                .like("username", "o")
                .ge("balance", 1000);

        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }
    

    // 或者你还可以这样写
    @Test
    void testQueryWrapper() {
       QueryWrapper<User> wrapper = new QueryWrapper<User>()
               .select("id", "username","info", "balance")
               .like("username", "o")
               .ge("balance", 1000);
        //    执行查询
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

更新数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
    @Test
    void testUpdateWrapper() {
         
        User user = new User();
        user.setBalance(114514);

        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .eq("username","jack");
        // user是你要更新的数据,wrapper是你要更新的条件
        userMapper.update(user,wrapper);
    }

插入数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
    @Test
    void testInsertWrapper() {

        User user = new User();
        user.setUsername("shuimo");
        user.setPassword("1234565165");
        user.setBalance(114514);
        user.setPhone("18688990011");
        user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());

        userMapper.insert(user);

    }

删除数据

1
2
3
4
5
6
    @Test
    void testDeleteWrapper() {
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .eq("username","shuimo");
        userMapper.delete(wrapper);
    }

批量修改

1
2
3
4
5
6
7
8
    @Test
    void testAllUpdateWrapper() {
        List<Long> ids = List.of(1L, 2L, 3L);
        UpdateWrapper<User> wrapper = new UpdateWrapper<User>()
                .set("balance", 0) // 设置了balance为0
                .in("id", ids);
        userMapper.update(null, wrapper);
    }

分页查询

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
    @Test
    void testQueryByPage(){
    //    分页查询
        int start = 0;
        int size = 2;
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .select("id", "username","info", "balance")
                .last("limit " + start + "," + size);
        userMapper.selectList(wrapper).forEach(System.out::println);

    }

自定义sql

查询两个表都有的数据

测试类

1
2
3
4
5
6
7
    @Test
    void testQuery(){
    //  复杂的查询,自定义sql,mq只支持单表
    // 查询address和address1表都有的数据
        List<Address> Address = addressMapper.query();
        Address.forEach(System.out::println);
    }

实体类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@Data
@TableName("address")
public class Address {
//    自增
    @TableId(type = IdType.AUTO)
    private Long id;

    private String userId;
    private String province;
    private String city;
    private String towm;
    private String mobile;
    private String street;
    private String contact;
    private String isDefault;
    private String nodes;
    private String deleted;
}

mapper类

1
2
3
4
5
6
7
8
public interface AddressMapper extends BaseMapper<Address> {

//    查询address和address1表都有的数据

    @Select("select * from address inner join address1 on address.id = address1.id")
    List<Address> query();

}

UserServiceImpl 类

1
2
3
4
5
// 通过继承复用了 ServiceImpl 中已经提前写好的方法
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

}

IUserService 接口

1
2
3
public interface IUserService extends IService<User> {

}

UserMapper 接口

1
2
3
4
//继承BaseMapper,指定泛型为User
public interface UserMapper extends BaseMapper<User> {

}

分析原理:

  • UserServiceImpl继承了ServiceImpl,并实现了IUserService接口,因此继承了ServiceImpl中的方法,并实现了IUserService中的方法

ServiceImpl.class

1
2
3
4
// ServiceImpl.class 是一个泛型类,继承了BaseMapper<T>,并实现了IService<T>接口
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {

}

实际上相当于

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26


public class UserServiceImpl implements IUserService {
    @Autowired
    private UserMapper userMapper;

    // 实现save方法
    @Override
    public boolean save(User user) {
        return userMapper.insert(user) > 0;
    }

    // 实现getById方法
    @Override
    public User getById(Long id) {
        return userMapper.selectById(id);
    }

    // 实现list方法
    @Override
    public List<User> list() {
        return userMapper.selectList(null);
    }

    // 其他所有CRUD方法...
}

MybatisPlus不仅提供了BaseMapper,还提供了通用的Service接口及默认实现,封装了一些常用的service模板方法。

通用接口为IService,默认实现为ServiceImpl,其中封装的方法可以分为以下几类:

  • save:新增
  • remove:删除
  • update:更新
  • get:查询单个结果
  • list:查询集合结果
  • count:计数
  • page:分页查询

CRUD

  • save是新增单个元素
  • saveBatch是批量新增
  • saveOrUpdate是根据id判断,如果数据存在就更新,不存在则新增
  • saveOrUpdateBatch是批量的新增或修改
  • removeById:根据id删除
  • removeByIds:根据id批量删除
  • removeByMap:根据Map中的键值对为条件删除
  • remove(Wrapper):根据Wrapper条件删除

自定义方法

1
2
3
4
5
6
@PutMapping("{id}/deduction/{money}")
@ApiOperation("扣减用户余额")
public Json deductBalance(@PathVariable("id") Long id, @PathVariable("money")Integer money){
    userService.deductBalance(id, money);
    return new Json("{\"code\":200,\"msg\":\"success\",\"data\":null}");
}
1
2
3
4
5
6
public interface IUserService extends IService<User> {

// 自定义的方法
    void deductBalance(Long id, Integer money);

}

Service层

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@Service // 交给Spring管理
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Override
    public void deductBalance(Long id, Integer money){
        // 获取用户,这个是BaseMapper中的方法,所以不需要自己写
        User user = getById(id);

        if (user == null || user.getStatus() == 2) {
            throw new RuntimeException("用户状态异常");
        }
        if (user.getBalance() < money) {
            throw new RuntimeException("用户余额不足");
        }
        // 这个方法是不存在的,所以要手动创建
        baseMapper.deductMoneyById(id, money);
    }
}

Mapper层

1
2
3
4
5
6
public interface UserMapper extends BaseMapper<User> {
    // sql你可以写进xml文件,也可以写进接口中
    @Update("UPDATE shuimo_user SET balance = balance - #{money} WHERE id = #{id}")
    void deductMoneyById(@Param("id") Long id, Integer money);

}
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计