MyBatisPlus学习

课程链接https://b11et3un53m.feishu.cn/wiki/PsyawI04ei2FQykqfcPcmd7Dnsc


只需要继承BaseMapper就能省去所有的单表CRUD

为了简化单表CRUD,MybatisPlus提供了一个基础的BaseMapper接口,其中已经实现了单表的CRUD

因此我们自定义的Mapper只要实现了这个BaseMapper,就无需自己实现单表CRUD了

常用注解

如何确定使用哪张表 ?

BaseMapper泛型中的User就是与数据库对应的PO.

@TableName(“user”)

@TableId标识实体类中的主键字段

@TableField(“isMarried”)普通字段注解

一般情况下我们并不需要给字段添加@TableField注解,一些特殊情况除外:

  • 成员变量名与数据库字段名不一致
  • 成员变量是以isXXX命名,按照JavaBean的规范,MybatisPlus识别字段时会把is去除,这就导致与数据库不符。
  • 成员变量名与数据库一致,但是与数据库的关键字冲突。使用@TableField注解给字段名添加转义字符:````
@TableName("user")
public class User {
    @TableId
    private Long id;
    private String name;
    private Integer age;
    @TableField("isMarried")
    private Boolean isMarried;
    @TableField("concat")
    private String concat;
}

支持手写yaml

mybatis-plus:
  mapper-locations: "classpath*:/mapper/**/*.xml" # Mapper.xml文件地址,当前这个是默认值。

条件查询

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

无论是修改、删除、查询,都可以使用QueryWrapper来构建查询条件。

@Test
void testQueryWrapper() {
    // 1.构建查询条件 where name like "%o%" AND balance >= 1000
    QueryWrapper<User> wrapper = new QueryWrapper<User>()
            .select("id", "username", "info", "balance")
            .like("username", "o")
            .ge("balance", 1000);
    // 2.查询数据
    List<User> users = userMapper.selectList(wrapper);
    users.forEach(System.out::println);
}
@Test
void testUpdateByQueryWrapper() {
    // 1.构建查询条件 where name = "Jack"
    QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username", "Jack");
    // 2.更新数据,user中非null字段都会作为set语句
    User user = new User();
    user.setBalance(2000);
    userMapper.update(user, wrapper);
}

基于BaseMapper中的update方法更新时只能直接赋值,对于一些复杂的需求就难以实现

@Test
void testUpdateWrapper() {
    List<Long> ids = List.of(1L, 2L, 4L);
    // 1.生成SQL
    UpdateWrapper<User> wrapper = new UpdateWrapper<User>()
            .setSql("balance = balance - 200") // SET balance = balance - 200
            .in("id", ids); // WHERE id in (1, 2, 4)
        // 2.更新,注意第一个参数可以给null,也就是不填更新字段和数据,
    // 而是基于UpdateWrapper中的setSQL来更新
    userMapper.update(null, wrapper);
}

论是QueryWrapper还是UpdateWrapper在构造条件的时候都需要写死字段名称,会出现字符串魔法值。这在编程规范中显然是不推荐的。 那怎么样才能不写字段名,又能知道字段名呢?

其中一种办法是基于变量的gettter方法结合反射技术。因此我们只要将条件对应的字段的getter方法传递给MybatisPlus,它就能计算出对应的变量名了。而传递方法可以使用JDK8中的方法引用Lambda表达式。 因此MybatisPlus又提供了一套基于Lambda的Wrapper,包含两个:

  • LambdaQueryWrapper
  • LambdaUpdateWrapper
@Test
void testLambdaQueryWrapper() {
    // 1.构建条件 WHERE username LIKE "%o%" AND balance >= 1000
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.lambda()
            .select(User::getId, User::getUsername, User::getInfo, User::getBalance)
            .like(User::getUsername, "o")
            .ge(User::getBalance, 1000);
    // 2.查询
    List<User> users = userMapper.selectList(wrapper);
    users.forEach(System.out::println);
}

自定义SQL

@Test
void testCustomWrapper() {
    // 1.准备自定义查询条件
    List<Long> ids = List.of(1L, 2L, 4L);
    QueryWrapper<User> wrapper = new QueryWrapper<User>().in("id", ids);

    // 2.调用mapper的自定义方法,直接传递Wrapper
    userMapper.deductBalanceByIds(200, wrapper);
}
public interface UserMapper extends BaseMapper<User> {
    @Select("UPDATE user SET balance = balance - #{money} ${ew.customSqlSegment}")
    void deductBalanceByIds(@Param("money") int money, @Param("ew") QueryWrapper<User> wrapper);
}

理论上来讲MyBatisPlus是不支持多表查询的,不过我们可以利用Wrapper中自定义条件结合自定义SQL来实现多表查询的效果。 例如,我们要查询出所有收货地址在北京的并且用户id在1、2、4之中的用户

多表关联

Service接口

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

用接口为IService,默认实现为ServiceImpl

public interface IUserService extends IService<User> {
    // 拓展自定义方法
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
                                                                                                        implements IUserService {
}

@GetMapping("/list")
@ApiOperation("根据id集合查询用户")
public List<UserVO> queryUsers(UserQuery query){
    // 1.组织条件
    String username = query.getName();
    Integer status = query.getStatus();
    Integer minBalance = query.getMinBalance();
    Integer maxBalance = query.getMaxBalance();
    LambdaQueryWrapper<User> wrapper = new QueryWrapper<User>().lambda()
            .like(username != null, User::getUsername, username)
            .eq(status != null, User::getStatus, status)
            .ge(minBalance != null, User::getBalance, minBalance)
            .le(maxBalance != null, User::getBalance, maxBalance);
    // 2.查询用户
    List<User> users = userService.list(wrapper);
    // 3.处理vo
    return BeanUtil.copyToList(users, UserVO.class);
}

在组织查询条件的时候,我们加入了 username != null 这样的参数,意思就是当条件成立时才会添加这个查询条件,类似Mybatis的mapper.xml文件中的<if>标签。这样就实现了动态查询条件效果了。

不过,上述条件构建的代码太麻烦了。 因此Service中对LambdaQueryWrapperLambdaUpdateWrapper的用法进一步做了简化。我们无需自己通过new的方式来创建Wrapper,而是直接调用lambdaQuerylambdaUpdate方法:

@GetMapping("/list")
@ApiOperation("根据id集合查询用户")
public List<UserVO> queryUsers(UserQuery query){
    // 1.组织条件
    String username = query.getName();
    Integer status = query.getStatus();
    Integer minBalance = query.getMinBalance();
    Integer maxBalance = query.getMaxBalance();
    // 2.查询用户
    List<User> users = userService.lambdaQuery()
            .like(username != null, User::getUsername, username)
            .eq(status != null, User::getStatus, status)
            .ge(minBalance != null, User::getBalance, minBalance)
            .le(maxBalance != null, User::getBalance, maxBalance)
            .list();
    // 3.处理vo
    return BeanUtil.copyToList(users, UserVO.class);
}

可以发现lambdaQuery方法中除了可以构建条件,还需要在链式编程的最后添加一个list(),这是在告诉MP我们的调用结果需要是一个list集合。这里不仅可以用list(),可选的方法有:

  • .one():最多1个结果
  • .list():返回集合结果
  • .count():返回计数结果

MybatisPlus会根据链式编程的最后一个方法来判断最终的返回结果。

与lambdaQuery方法类似,IService中的lambdaUpdate方法可以非常方便的实现复杂更新业务。

批量新增

IService中的批量新增功能使用起来非常方便

savebatch 想改语句,直接修改yaml 的一个开关

扩展功能

代码生成

MybatisPlus的插件

静态工具

有的时候Service之间也会相互调用,为了避免出现循环依赖问题,MybatisPlus提供一个静态工具类:Db,其中的一些静态方法与IService中方法签名基本一致,也可以帮助我们实现CRUD功能:

逻辑删除
通用枚举

数据库中是0,1

可以在java代码中变成枚举类

JSON类型处理器

数据库的user表中有一个info字段,是JSON类型而目前User实体类中却是String类型

插件功能

分页插件

在未引入分页插件的情况下,MybatisPlus是不支持分页功能的,IServiceBaseMapper中的分页方法都无法正常起效。 所以,我们必须配置分页插件。

VSMybatis

mybatis

<select id="queryUserByIdAndAddr" resultType="com.itheima.mp.domain.po.User">
      SELECT *
      FROM user u
      INNER JOIN address a ON u.id = a.user_id
      WHERE u.id
      <foreach collection="ids" separator="," item="id" open="IN (" close=")">
          #{id}
      </foreach>
      AND a.city = #{city}
  </select>

Mybatisplus

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


MyBatis和MyBatis-Plus(MyBatis Plus)都是流行的ORM(Object-Relational Mapping)框架,用于在Java应用程序中进行数据库操作。虽然MyBatis和MyBatis-Plus都提供了强大的数据库操作功能,但它们之间存在一些显著的差异。以下是对比和介绍:

MyBatis

MyBatis 是一个持久层框架,主要特点如下:

  1. 手动编写SQL:MyBatis需要开发者手动编写SQL语句,灵活性高,可以充分利用SQL的功能。
  2. XML映射文件:MyBatis使用XML文件来配置SQL语句和映射关系,也支持注解方式。
  3. 动态SQL支持:MyBatis提供了丰富的动态SQL支持,通过 <if>, <choose>, <where>, <set> 等标签,可以根据条件动态生成SQL语句。
  4. 多种缓存机制:MyBatis支持一级缓存(Session级别)和二级缓存(Mapper级别或全局级别)。
  5. 插件机制:MyBatis提供了插件机制,可以编写插件来拦截执行的核心方法(如Executor、StatementHandler等)。

优点

  • 灵活性高,适用于复杂查询。
  • SQL语句直观明确,便于优化和调试。

缺点

  • 需要大量手动编写SQL和映射配置文件,开发效率相对较低。
  • 对简单的CRUD操作来说,配置较为繁琐。

MyBatis-Plus

MyBatis-Plus 是基于MyBatis的增强工具包,主要特点如下:

  1. 简化CRUD操作:MyBatis-Plus提供了大量预定义的CRUD方法,极大地减少了手动编写SQL的工作量。
  2. 代码生成器:MyBatis-Plus提供了代码生成器,可以自动生成Mapper、Entity、Service、Controller等代码,提高开发效率。
  3. 条件构造器:MyBatis-Plus提供了条件构造器(Wrapper类),可以通过链式调用方式构建复杂的查询条件。
  4. 多种插件支持:MyBatis-Plus内置分页插件、性能分析插件、乐观锁插件、SQL注入器等,增强了MyBatis的功能。
  5. 元数据扫描:MyBatis-Plus可以自动扫描数据库表结构,生成相应的实体类和Mapper接口。

优点

  • 提高开发效率,简化常见的CRUD操作。
  • 内置了多种增强功能插件,减少了重复工作。
  • 通过条件构造器可以优雅地构建复杂的查询条件。

缺点

  • 灵活性不如手写SQL,对复杂查询可能需要回退到MyBatis的原始方式。
  • 与MyBatis相比,学习曲线稍微陡峭一些,需要熟悉MyBatis-Plus的扩展功能和用法。

对比总结

特性MyBatisMyBatis-Plus
SQL编写手动编写SQL,灵活性高自动生成CRUD,简化操作
动态SQL支持<if>, <choose>, <where>条件构造器,链式调用
映射配置XML映射文件或注解自动扫描数据库,代码生成器
插件机制提供插件机制,需手动编写内置分页、乐观锁等多种插件
缓存支持一级缓存、二级缓存继承MyBatis的缓存机制
开发效率需要手动编写,效率较低提高效率,减少重复工作
复杂查询灵活,适用于复杂查询灵活性较低,复杂查询需手动编写

示例代码对比

MyBatis 示例

Mapper接口:

public interface UserMapper {
    User selectById(Long id);
    List<User> selectByName(String name);
    void insertUser(User user);
    void updateUser(User user);
    void deleteUser(Long id);
}

XML映射文件:

<mapper namespace="com.example.mapper.UserMapper">
    <select id="selectById" resultType="User">
        SELECT * FROM users WHERE id = #{id}
    </select>
    <select id="selectByName" resultType="User">
        SELECT * FROM users WHERE name = #{name}
    </select>
    <insert id="insertUser">
        INSERT INTO users (name, age) VALUES (#{name}, #{age})
    </insert>
    <update id="updateUser">
        UPDATE users SET name = #{name}, age = #{age} WHERE id = #{id}
    </update>
    <delete id="deleteUser">
        DELETE FROM users WHERE id = #{id}
    </delete>
</mapper>

注解版

@Select("SELECT * FROM users WHERE id = #{id}")
User selectById(Long id);

@Select("SELECT * FROM users WHERE name = #{name}")
List<User> selectByName(String name);

@Insert("INSERT INTO users (name, age) VALUES (#{name}, #{age})")
@Options(useGeneratedKeys = true, keyProperty = "id")
void insertUser(User user);

@Update("UPDATE users SET name = #{name}, age = #{age} WHERE id = #{id}")
void updateUser(User user);

@Delete("DELETE FROM users WHERE id = #{id}")
void deleteUser(Long id);

MyBatis-Plus 示例

实体类:

@Data
@TableName("users")
public class User {
    private Long id;
    private String name;
    private Integer age;
}

Mapper接口(继承BaseMapper):

public interface UserMapper extends BaseMapper<User> {
}

Service类:

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    public User getById(Long id) {
        return userMapper.selectById(id);
    }

    public List<User> getByName(String name) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", name);
        return userMapper.selectList(queryWrapper);
    }

    public void saveUser(User user) {
        userMapper.insert(user);
    }

    public void updateUser(User user) {
        userMapper.updateById(user);
    }

    public void deleteUser(Long id) {
        userMapper.deleteById(id);
    }
}

通过上述对比,可以看到MyBatis-Plus简化了很多重复的工作,提供了更加便捷的CRUD操作,同时保留了MyBatis灵活的SQL编写能力。根据具体需求,可以选择使用MyBatis或MyBatis-Plus来进行项目开发。

  • 53
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值