三:Mybatis-Plus通用CRUD

    科技2022-07-16  142

    MyBatis-Plus为我们提供了BaseMapper,我们只需要继承BaseMapper就可以直接使用简单的增删改查功能。

    一:Create(Insert)

    int insert(T entity); @Test void testMyBatisPlus() { // INSERT INTO tbl_user ( username, name ) VALUES ( ?, ? ) User user = new User(); user.setUsername("gaozhanlong"); user.setName("高占龙"); // 返回受影响的行数 // 插入时如果属性值为null则不加入到SQL中。 // INSERT INTO tbl_user ( id, username, password, name ) VALUES ( ?, ?, ?, ? ) int affectRows = userMapper.insert(user); // 插入后主键id会赋值给实体 Long userId = user.getId(); System.out.println("affectRows=" + affectRows + ", userId=" + userId); } public class User implements Serializable { /** * 主键 */ @TableId(type = IdType.AUTO) private Long id; }

    数据库的主键对应实体中属性需要使用@TableId注解标注,并指明主键id的生成策略,常用的有AUTO(数据库自增)、ASSIGN_ID(雪花算法),当插入成功后会将主键id值回显给实体对象,一般情况下id生成策略都使用ATUO,只有在有分表需求的时候才使用ASSIGN_ID(雪花算法)。

    注意:最新版本的mybatis-plus中的雪花算法好像不需要配置数据中心ID和机器ID,它们都是自动计算出来的:

    mybatis-plus.global-config.datacenter-id 根据服务器的Mac地址来计算mybatis-plus.global-config.worker-id 根据datacenter-id和java虚拟中的bean数量来计算。

    使用@TableId(type = IdType.AUTO)这种将注解标注在主键id属性上属于局部主键策略,我们也可以在application.yml中配置全局主键策略,当配置了全局id生成策略并且主键为“id”此时不用显式的使用@TableId注解,如果同时配置了全局策略和局部策略,那么局部策略优于全局策略。

    # 配置mybatis plus 全局的id生成策略 mybatis-plus.global-config.db-config.id-type=auto

    二:Delete

    // 根据 entity 条件,删除记录 int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper); // 删除(根据ID 批量删除) int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); // 根据 ID 删除 int deleteById(Serializable id); // 根据 columnMap 条件,删除记录 int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap); @Test public void testDelete() { // DELETE FROM tbl_user WHERE id=? int affectRows = userMapper.deleteById(100L); // DELETE FROM tbl_user WHERE id IN ( ? , ? , ? ) int num = userMapper.deleteBatchIds(Arrays.asList(1L, 2L, 3L)); // 多条件删除,逻辑运算符使用and连接,关系运算符使用=连接,如果值为null表示 is null // DELETE FROM tbl_user WHERE username = ? AND status IS NULL Map<String, Object> whereMap = new HashMap<>(); whereMap.put("username", "gaozhanlong"); whereMap.put("status", null); int rows = userMapper.deleteByMap(whereMap); // 使用QueryWrapper构造where条件(这种方式最灵活,可以构造任意关系运算符和逻辑运算符) // DELETE FROM tbl_user WHERE (age > ? AND username LIKE ?) QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.gt("age", 30).likeRight("username", "xiao"); int count = userMapper.delete(wrapper); }

    三:Update

    // 根据 whereEntity 条件,更新记录 int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper); // 根据 ID 修改 int updateById(@Param(Constants.ENTITY) T entity); @Test void testMyBatisPlus() { // UPDATE tbl_user SET age=?, status=? WHERE id=? User user = new User(); user.setId(1L); user.setAge(50); user.setStatus(2); int affectRows = userMapper.updateById(user); System.out.println(affectRows); }

    注意:修改时如果属性为null也是不会加入到SQL语句中来的。

    @Test public void testUpdate(){ User user = new User(); user.setAge(35); user.setRemark("重庆军统王牌特工,表面残酷狠辣的军统特务“鬼子六”"); QueryWrapper<User> queryWrapper = new QueryWrapper(); queryWrapper.eq("username", "sixbrother").gt("age", 20); // UPDATE tbl_user SET age=?, remark=? WHERE (username = ? AND age > ?) int affectRows = userMapper.update(user, queryWrapper); System.out.println(affectRows); } @Test void testMyBatisPlus() { // UPDATE tbl_user SET age=?, status=? WHERE (id = ?) User user = new User(); user.setId(1L); user.setAge(50); user.setStatus(2); QueryWrapper<User> queryWrapper = new QueryWrapper<User>().eq("id", 100L); int affectRows = userMapper.update(user, queryWrapper); System.out.println(affectRows); }

    UpdateWrapper可以通过set方法来设置字段的值。

    @Test void testMyBatisPlus() { // UPDATE tbl_user SET age=?,status=? WHERE (id = ?) UpdateWrapper<User> updateWrapper = new UpdateWrapper<User>() .set("age", 30) .set("status", 2) .eq("id", 100L); int affectRows = userMapper.update(null, updateWrapper); System.out.println(affectRows); }

    UpdateWrapper可以通过setSql() 采用SQL语法来设置值。

    @Test void testMyBatisPlus() { // UPDATE tbl_user SET age=?,status = 2 WHERE (id = ?) LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<User>() .set(User::getAge, 30) .setSql("status = 2") .eq(User::getId, 100L); int affectRows = userMapper.update(null, updateWrapper); System.out.println(affectRows); }

    注意:

    QueryWrapper:用于构造where条件的,SQL中的条件在QueryWrapper中都有对应的方法。QueryWrapper默认是使用and 并且来连接各个条件的。UpdateWrapper:用于构造update语句,比QueryWrapper多了一个set()方法用于修改值,也可以使用QueryWrapper中的方法来构造where条件。

    四:Retrieve(Select)

    // 根据 ID 查询 T selectById(Serializable id); // 根据 entity 条件,查询一条记录 T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询(根据ID 批量查询) List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); // 根据 entity 条件,查询全部记录 List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询(根据 columnMap 条件) List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap); // 根据 Wrapper 条件,查询全部记录 List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值 List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 根据 entity 条件,查询全部记录(并翻页) IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 根据 Wrapper 条件,查询全部记录(并翻页) IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 根据 Wrapper 条件,查询总记录数 Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); @Test public void testSelect() { // SELECT * FROM tbl_user WHERE id=? User user = userMapper.selectById(1L); System.out.println(user); // SELECT * FROM tbl_user WHERE id IN ( ? , ? ) List<User> users = userMapper.selectBatchIds(Arrays.asList(1L, 2L)); System.out.println(users); // 查询一条,如果有多条满足条件的数据会报错 // SELECT * FROM tbl_user WHERE (username = ?) QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("username", "sixbrother"); User user1 = userMapper.selectOne(queryWrapper); // 查询满足条件的条数 // SELECT COUNT( 1 ) FROM tbl_user WHERE (username LIKE ?) QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.like("username", "xiao"); Integer count = userMapper.selectCount(wrapper); // SELECT * FROM tbl_user WHERE (username LIKE ?) List<User> userList = userMapper.selectList(wrapper); }

    selectMaps()通常用于统计查询,因为一般统计的结果字段都不在实体类中。

    @Test void testMyBatisPlus() { // SELECT gender,count(*) as count,avg(age) as avg_age FROM tbl_user GROUP BY gender QueryWrapper<User> queryWrapper = Wrappers.<User>query() .select("gender", "count(*) as count", "avg(age) as avg_age").groupBy("gender"); List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper); System.out.println(maps); }

    五:自定义SQL

    自定义SQL就是又想自己写SQL语句又想使用MyBatis-Plus中的条件构造器Wrapper,MyBatis-Plus中可以支持此方式,通过使用@Param注解即可引用条件构造器。

    BaseMapper中的很多方法参数都使用了@Param注解进行标注了,这就意味着我们可以在原生的MyBatis中使用这个参数(可以在MyBatis注解中也可以在xml文件中),例如使用@Param(Constants.WRAPPER) 定义参数名,在MyBatis中使用固定的写法${ew.customSqlSegment}来引用MyBatis-Plus中的条件构造器。

    @Test void testMyBatisPlus() { // delete from tbl_user WHERE (id = ? OR age > ?) QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("id", 100).or().gt("age", 30); userMapper.myDelete(wrapper); } public interface UserMapper extends BaseMapper<User> { // 注意SQL语句不需要加where关键字 @Delete("delete from tbl_user ${ew.customSqlSegment}") void myDelete(@Param(Constants.WRAPPER) QueryWrapper<User> wrapper); }

    六:@TableField

    @TableField用于指定字段的一些属性,常用的场景有:

    对象中的属性名和字段名不一致的问题,如表中使用user_id作为主键,而实体中使用id作为属性名,此时需要配置两者的映射关系。 @TableName("tbl_user") public class User implements Serializable { /** * 主键 */ @TableId(type = IdType.AUTO) @TableField(value = "user_id") private Long id; } 对象中的属性字段在表中不存在的问题。 @TableName("tbl_user") public class User implements Serializable { /** 数据库中不存在的字段 */ @TableField(exist = false) private String mock; } 查询时不查询指定的字段,如有些字段只是服务器在使用,没必要暴露出去 @TableName("tbl_user") public class User implements Serializable { /** * 版本号 */ @TableField(select = false) private String version; /** * 是否删除(0: 未删除,1:已删除) */ @TableField(select = false) private Integer deleted; }
    Processed: 0.010, SQL: 8