MyBatis-Plus基本CRUD

简介: MyBatis-Plus基本CRUD

三、基本CRUD

1、BaseMapper

MyBatis-Plus中的基本CRUD在内置的BaseMapper中都已得到了实现,我们可以直接使用

2、插入

    //测试插入
    @Test
    public void testInsert() {
        User user = new User();
        // INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
        user.setName("张三");
        user.setAge(23);
        user.setEmail("zhangsan@qq.com");
        int res = userMapper.insert(user);//打印出来的是受影响的行数
        System.out.println("res: " + res);//res: 1
        System.out.println("id: " + user.getId());//id: 1623636806420439041
    }

最终执行的结果,所获取的id为1623636806420439041

这是因为MyBatis-Plus在实现插入数据时,会默认基于雪花算法的策略生成id

3、删除

a>通过id删除记录

    //通过id删除用户信息
    @Test
    public void testDeleteById() {
        //DELETE FROM user WHERE id=?
        int res = userMapper.deleteById(1623636806420439041L);//打印出来的是受影响的行数
        System.out.println("受影响行数:" + res);
    }

b>通过id批量删除记录

    @Test
    public void testDeleteBatchIds(){
        List<Long> idList = Arrays.asList(104L, 105L, 106L);
        //通过多个id批量删除
        //DELETE FROM user WHERE id IN ( ? , ? , ? )
        int i = userMapper.deleteBatchIds(idList);//打印出来的是受影响的行数
        System.out.println("受影响行数:" + i);//受影响行数:3
    }

c>通过map条件删除记录

    //通过map条件删除记录
    @Test
    public void testDeleteByMap(){
        //根据map集合中所设置的条件删除记录
        //DELETE FROM user WHERE name = ? AND age = ?
        Map<String, Object> map = new HashMap<>();
        map.put("age", 18);
        map.put("name", "ls4");
        int i = userMapper.deleteByMap(map);//打印出来的是受影响的行数
        System.out.println("受影响行数:" + i);//受影响行数:1
    }

4、通过id修改一条记录

    @Test
    public void testUpdateById(){
        User user = new User();
        user.setId(6L);
        user.setName("z3");
        user.setAge(23);
        user.setEmail("z3@qq.com");
        //UPDATE user SET name=?, age=? WHERE id=?
        int i = userMapper.updateById(user);//打印出来的是受影响的行数
        System.out.println("受影响行数:" + i);//受影响行数:1
    }

5、查询

a>根据id查询用户信息

    //根据id查询用户信息
    @Test
    public void testSelectById(){
        // SELECT id,name,age,email FROM user WHERE id=?
        User user = userMapper.selectById(4L);
        System.out.println(user);
    }

b>根据多个id查询多个用户信息

    @Test
    public void testSelectBatchIds(){
        List<Long> idList = Arrays.asList(1L, 2L, 3L);
        //SELECT id,name,age,email FROM user WHERE id IN ( ? , ? , ? )
        for (User user : userMapper.selectBatchIds(idList)) {
            System.out.println(user);
        }
    }

c>通过map条件查询用户信息

    @Test
    public void testSelectByMap(){
        Map<String,Object> map = new HashMap<>();
        map.put("name", "jerry");
        map.put("age", 21);
        List<User> users = userMapper.selectByMap(map);
        users.forEach(System.out::println);
    }

d>查询所有数据

    @Test
    public void testSelectList(){
        //查询所有用户信息
        //SELECT id,name,age,email FROM user
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }


通过观察BaseMapper中的方法,大多方法中都有Wrapper类型的形参,此为条件构造器,可针 对于SQL语句设置不同的条件,若没有条件,则可以为该形参赋值null,即查询(删除/修改)所有数据

6、通用Service

说明:


通用 Service CRUD 封装IService接口,进一步封装 CRUD 采用 get 查询单行 remove 删 除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆,


泛型 T 为任意实体对象


建议如果存在自定义通用 Service 方法的可能,请创建自己的 IBaseService 继承 Mybatis-Plus 提供的基类


官网地址:https://baomidou.com/pages/49cc81/#service-crud-%E6%8E%A5%E5%8F% A3


a>IService

MyBatis-Plus中有一个接口 IService和其实现类 ServiceImpl,封装了常见的业务层逻辑


详情查看源码IService和ServiceImpl

b>创建Service接口和实现类

/**
 * UserService继承IService模板提供的基础功能
 */
public interface UserService extends IService<User> {
}
/**
 * ServiceImpl实现了IService,提供了IService中基础功能的实现
 * 若ServiceImpl无法满足业务需求,则可以使用自定的UserService定义方法,并在实现类中实现
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{
}

c>测试查询记录数

    @Autowired
    UserService userService;
    //测试查询记录数
    @Test
    public void testGetCount() {
        long count = userService.count();
        //SELECT COUNT( * ) FROM user
        System.out.println("总记录数:" + count);
    }

d>测试批量插

    //测试批量插入
    @Test
    public void testSaveBatch() {
        ArrayList<User> users = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            User user = new User();
            user.setName("jerry" + i);
            user.setAge(18 + i);
            users.add(user);
        }
        //INSERT INTO user ( id, name, age ) VALUES ( ?, ?, ? )
        userService.saveBatch(users);
    }

四、常用注解

1、@TableName

经过以上的测试,在使用MyBatis-Plus实现基本的CRUD时,我们并没有指定要操作的表,只是在 Mapper接口继承BaseMapper时,设置了泛型User,而操作的表为user表


由此得出结论,MyBatis-Plus在确定操作的表时,由BaseMapper的泛型决定,即实体类型决 定,且默认操作的表名和实体类型的类名一致

a>问题

若实体类类型的类名和要操作的表的表名不一致,会出现什么问题?

我们将表user更名为t_user,测试查询功能 程序抛出异常,Table ‘mybatis_plus.user’ doesn’t exist,因为现在的表名为t_user,而默认操作 的表名和实体类型的类名一致,即user表

b>通过@TableName解决问题

在实体类类型上添加@TableName(“t_user”),标识实体类对应的表,即可成功执行SQL语句


dfcdf6a62ea546f1be329e2c8b2d9a8c.png

c>通过全局配置解决问题

在开发的过程中,我们经常遇到以上的问题,即实体类所对应的表都有固定的前缀,例如t_或tb_

此时,可以使用MyBatis-Plus提供的全局配置,为实体类所对应的表名设置默认的前缀,那么就 不需要在每个实体类上通过@TableName标识实体类对应的表

# 配置MyBatis日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
    # 配置MyBatis-Plus操作表的默认前缀
      table-prefix: t_

2、@TableId

经过以上的测试,MyBatis-Plus在实现CRUD时,会默认将id作为主键列,并在插入数据时,默认 基于雪花算法的策略生成id

a>问题

若实体类和表中表示主键的不是id,而是其他字段,例如uid,MyBatis-Plus会自动识别uid为主 键列吗?

我们实体类中的属性id改为uid,将表中的字段id也改为uid,测试添加功能

程序抛出异常,Field ‘uid’ doesn’t have a default value,说明MyBatis-Plus没有将uid作为主键 赋值

b>通过@TableId解决问题

在实体类中uid属性上通过@TableId将其标识为主键,即可成功执行SQL语句


0da2fffbfb6f40648d64d292159a206f.png

c>@TableId的value属性

若实体类中主键对应的属性为id,而表中表示主键的字段为uid,此时若只在属性id上添加注解 @TableId,

则抛出异常Unknown column ‘id’ in ‘field list’,即MyBatis-Plus仍然会将id作为表的 主键操作,而表中表示主键的是字段uid


此时需要通过@TableId注解的value属性,指定表中的主键字段,@TableId(“uid”)或 @TableId(value=“uid”)


https://jerry-jy.blog.csdn.net/article/details/128991782?spm=1001.2014.3001.5502#:~:text=TableId(value%3D%E2%80%9Cuid%E2%80%9D)-,d%3E%40TableId%E7%9A%84type%E5%B1%9E%E6%80%A7,%E5%B8%B8%E7%94%A8%E7%9A%84%E4%B8%BB%E9%94%AE%E7%AD%96%E7%95%A5%EF%BC%9A,-%E5%80%BC

d>@TableId的type属性

type属性用来定义主键策略

常用的主键策略:

描述
IdType.ASSIGN_ID(默 认) 基于雪花算法的策略生成数据id,与数据库id是否设置自增无关
IdType.AUTO 使用数据库的自增策略,注意,该类型请确保数据库设置了id自增, 否则无效

配置全局主键策略:

# 配置MyBatis日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
    # 配置MyBatis-Plus操作表的默认前缀
      table-prefix: t_
      # 配置MyBatis-Plus的主键策略
      id-type: auto

3、@TableField

经过以上的测试,我们可以发现,MyBatis-Plus在执行SQL语句时,要保证实体类中的属性名和 表中的字段名一致 如果实体类中的属性名和字段名不一致的情况,会出现什么问题呢?

a>情况1

若实体类中的属性使用的是驼峰命名风格,而表中的字段使用的是下划线命名风格

例如实体类属性userName,表中字段user_name

此时MyBatis-Plus会自动将下划线命名风格转化为驼峰命名风格

相当于在MyBatis中配置

b>情况2

若实体类中的属性和表中的字段不满足情况1

例如实体类属性name,表中字段username

此时需要在实体类属性上使用@TableField(“username”)设置属性所对应的字段名

883c5600af0e4e06b0f08a071a75db00.png

4、@TableLogic

a>逻辑删除

  • 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据
  • 逻辑删除:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据库 中仍旧能看到此条数据记录
  • 使用场景:可以进行数据恢复

b>实现逻辑删除

step1:数据库中创建逻辑删除状态列,设置默认值为0



a3ce70937ac14995ac6610a5b3236f1b.png

step2:实体类中添加逻辑删除属性


3266df3825ab4e7b811e1f608c688f05.png

step3:测试

    @Test
    public void test(){
        //UPDATE user SET is_deleted=1 WHERE id=? AND is_deleted=0
        int i = userMapper.deleteById(1623660102079778820L);
        System.out.println("受影响行数:" + i);//受影响行数:1
    }

五、条件构造器和常用接口

1、wapper介绍

2、QueryWrapper

a>例1:组装查询条件

查询用户名包含j,年龄在20到30之间,并且邮箱不为null的用户信息

    //查询用户名包含j,年龄在20到30之间,并且邮箱不为null的用户信息
    @Test
    public void test01(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name", "j")
                .between("age", 20, 30)
                .isNotNull("email");
        //SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (name LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
        List<User> users = userMapper.selectList(queryWrapper);
        users.forEach(System.out::println);
    }

b>例2:组装排序条件

按年龄降序查询用户,如果年龄相同则按id升序排列

    //按年龄降序查询用户,如果年龄相同则按id升序排列
    @Test
    public void test02(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("age")
                .orderByAsc("id");
        //SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 ORDER BY age DESC,id ASC
        List<User> users = userMapper.selectList(queryWrapper);
        users.forEach(System.out::println);
    }

c>例3:组装删除条件

删除email为空的用户

    @Test
    public void test03(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //UPDATE user SET is_deleted=1 WHERE is_deleted=0 AND (email IS NULL)
        //条件构造器也可以构建删除语句的条件         
        queryWrapper.isNull("email");
        int delete = userMapper.delete(queryWrapper);
        System.out.println(delete);
    }

d>例4:条件的优先级

//将(年龄大于20并且用户名中包含有a)或邮箱为null的用户信息修改

    @Test
    public void test04(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.gt("age", 20)
                .like("name", "a")
                .or()
                .isNull("email");
        User user = new User();
        user.setAge(20);
        user.setName("Tom1");
        user.setEmail("user@qq.com");
        //UPDATE user SET name=?, age=?, email=? WHERE is_deleted=0 AND (age > ? AND name LIKE ? OR email IS NULL)
        int i = userMapper.update(user, queryWrapper);
        System.out.println("受影响行数:" + i);//受影响行数:1
    }

e>例5:组装select子句

//查询用户信息的username和age字段

    @Test
    public void test05(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("name","age");
        //SELECT name,age FROM user WHERE is_deleted=0
        //selectMaps()返回Map集合列表,通常配合select()使用,避免User对象中没有被查询到的列值为null
        List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
        maps.forEach(System.out::println);
    }

f>例6:实现子查询

//查询id小于等于3的用户信息

    //查询id小于等于3的用户信息
    @Test
    public void test06(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (id IN (select id from user where id <= 3))
        queryWrapper.inSql("id", "select id from user where id <= 3");
        List<User> users = userMapper.selectList(queryWrapper);
        users.forEach(System.out::println);
    }

3、UpdateWrapper

//将(年龄大于20或邮箱为null)并且用户名中包含有a的用户信息修改

    @Test
    public void test07(){
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        //UPDATE user SET age=?,email=? WHERE is_deleted=0 AND (name LIKE ? AND (age > ?) OR email IS NULL)
        updateWrapper.set("age", 18)
                .set("email", "admin@qq.com")
                .like("name", "a")
                .and(i->i.gt("age", 18)).or().isNull("email");
        int i = userMapper.update(null, updateWrapper);
        System.out.println("受影响行数:" + i);//受影响行数:1
    }

4、condition

在真正开发的过程中,组装条件是常见的功能,而这些条件数据来源于用户输入,是可选的,因 此我们在组装这些条件时,必须先判断用户是否选择了这些条件,若选择则需要组装该条件,若 没有选择则一定不能组装,以免影响SQL执行的结果


不使用condition的代码

    @Test
    public void test08(){
        //定义查询条件,有可能为null(用户未输入或未选择)
        String name = null;
        Integer ageBegin = 10;
        Integer ageEnd = 24;
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //StringUtils.isNotBlank()判断某字符串是否不为空且长度不为0且不由空白符(whitespace)构成
        if (StringUtils.isNotBlank(name)){
            queryWrapper.like("name", "a");
        }
        if(ageBegin != null){
            queryWrapper.ge("age", ageBegin);
        }
        if(ageEnd != null){
            queryWrapper.le("age", ageEnd);
        }
        //SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (age >= ? AND age <= ?)
        List<User> users = userMapper.selectList(queryWrapper);
        users.forEach(System.out::println);
    }

使用condition

    @Test
    public void test08Condition() {
        //定义查询条件,有可能为null(用户未输入或未选择)
        String name = null;
        Integer ageBegin = 10;
        Integer ageEnd = 24;
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(name), "name", "a")
                .gt(ageBegin != null, "age", ageBegin)
                .lt(ageEnd != null, "age", ageEnd);
        List<User> users = userMapper.selectList(queryWrapper);
        users.forEach(System.out::println);
    }

END

相关文章
|
6月前
|
SQL Java 数据库连接
|
6月前
MyBatisPlus-标准数据层CRUD功能制作
MyBatisPlus-标准数据层CRUD功能制作
69 0
|
6月前
|
SQL Java 数据库连接
JAVAEE框架技术之7-myBatis ORM框架入门基础CRUD
JAVAEE框架技术之7-myBatis ORM框架入门基础CRUD
159 0
JAVAEE框架技术之7-myBatis ORM框架入门基础CRUD
|
6月前
|
XML Java 数据库连接
MyBatis深入探索:原生API与注解方式实现CRUD操作
MyBatis深入探索:原生API与注解方式实现CRUD操作
121 0
|
6月前
|
Java 关系型数据库 数据库连接
【MyBatisPlus 】MyBatisPlus CRUD 工程使用
【1月更文挑战第19天】【MyBatisPlus 】MyBatisPlus CRUD 工程使用
|
25天前
|
SQL Java 数据库连接
MyBatis-Plus:简化 CRUD 操作的艺术
MyBatis-Plus 是一个基于 MyBatis 的增强工具,它旨在简化 MyBatis 的使用,提高开发效率。
50 1
MyBatis-Plus:简化 CRUD 操作的艺术
|
1月前
|
SQL Java 数据库连接
Mybatis方式完成CRUD操作
Mybatis方式完成CRUD操作
39 0
|
5月前
|
缓存 Java 数据库连接
我们后端程序员不是操作MyBatis的CRUD Boy
大家好,我是南哥。一个对Java程序员进阶成长颇有研究的人,今天我们接着新的一篇Java进阶指南。为啥都戏称后端是CRUD Boy?难道就因为天天怼着数据库CRUD吗?要我说,是这个岗位的位置要的就是你CRUD,你不得不CRUD。哪有公司天天能给你搭建高并发、高可用、大数据框架的活呢,一条业务线总要成长吧,慢慢成熟了就要装修工来缝缝补补、美化美化,也就是CRUD的活。不能妄自菲薄CRUD Boy,我们是后端工程师。今天来指南下操作数据库之MyBatis框架。
126 3
我们后端程序员不是操作MyBatis的CRUD Boy
MybatisPlus-标准CRUD制作,新增boolean save(T t),删除 ~ delete(int id),修改 ~ update(T t),根据id查询,T getById....
MybatisPlus-标准CRUD制作,新增boolean save(T t),删除 ~ delete(int id),修改 ~ update(T t),根据id查询,T getById....
|
5月前
|
SQL XML Java
【MyBatis】 MyBatis框架下的高效数据操作:深入理解增删查改(CRUD)
【MyBatis】 MyBatis框架下的高效数据操作:深入理解增删查改(CRUD)
45 1