java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > MyBatis无缝转MyBatis-plus

MyBatis无缝转MyBatis-plus的基本使用

作者:STZ程序猿

本文介绍了使用MyBatis-plus来优化MyBatis的使用,包括引入依赖、改造Mapper、实体类注解使用、Service层方法改造等,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1.引入依赖

引入MyBatis-plus依赖取代MyBatis

<!--mybatis-plus起步依赖-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.1</version>
</dependency>

2.改造Mapper

继承BaseMapper

public interface 原来的Mapper extends BaseMapper<这里填入这个mapper对应的实体类> {

}

3.改造实体类

需要用到以下三个注解

@TableName("这里填写表名") // 指定数据库表的对应

@TableId(value = "这里填写主键字段名",type = IdType.AUTO) // 指定主键的对应

@TableField("这里填写字段名") // 指定字段的对应

一个完整的实体类参考如下:

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("table_name")
public class tableName implements Serializable {
    @TableId(value = "table_id",type = IdType.AUTO)
    private Long tableId;
    @TableField("table_field")
    private String tableField;
}

注意:

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

支持的其它属性如下:

属性类型必填默认值描述
valueString""数据库字段名
existbooleantrue是否为数据库表字段
conditionString""字段 where 实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的 %s=#{%s},参考(opens new window)
updateString""字段 update set 部分注入,例如:当在version字段上注解update="%s+1" 表示更新时会 set version=version+1 (该属性优先级高于 el 属性)
insertStrategyEnumFieldStrategy.DEFAULT举例:NOT_NULL insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>)
updateStrategyEnumFieldStrategy.DEFAULT举例:IGNORED update table_a set column=#{columnProperty}
whereStrategyEnumFieldStrategy.DEFAULT举例:NOT_EMPTY where <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if>
fillEnumFieldFill.DEFAULT字段自动填充策略
selectbooleantrue是否进行 select 查询
keepGlobalFormatbooleanfalse是否保持使用全局的 format 进行处理
jdbcTypeJdbcTypeJdbcType.UNDEFINEDJDBC 类型 (该默认值不代表会按照该值生效)
typeHandlerTypeHander类型处理器 (该默认值不代表会按照该值生效)
numericScaleString""指定小数点后保留的位数

4-1.改造Service

第一种情况:使用条件构造器

QueryWrapper

除了新增以外,修改、删除、查询的SQL语句都需要指定where条件。因此BaseMapper中提供的相关方法除了以id作为where条件以外,还支持更加复杂的where条件。

基本用法:

List<xx> xxList = xxMapper.selectList(new QueryWrapper<xx>());

mapper对象调用方法,里面传递一个queryWrapper对象

其它方法:

UpdateWrapper

基于BaseMapper中的update方法更新时只能直接赋值,对于一些复杂的需求就难以实现。 例如:更新id为1,2,4的用户的余额,扣200,对应的SQL应该是:

UPDATE user SET balance = balance - 200 WHERE id in (1, 2, 4)

SET的赋值结果是基于字段现有值的,这个时候就要利用UpdateWrapper中的setSql功能了:

@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);
}

LambdaQueryWrapper

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

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

分别对应QueryWrapper和UpdateWrapper

其使用方式如下:

@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

在演示UpdateWrapper的案例中,我们在代码中编写了更新的SQL语句:

这种写法在某些企业也是不允许的,因为SQL语句最好都维护在持久层,而不是业务层。就当前案例来说,由于条件是in语句,只能将SQL写在Mapper.xml文件,利用foreach来生成动态SQL。 这实在是太麻烦了。假如查询条件更复杂,动态SQL的编写也会更加复杂。

所以,MybatisPlus提供了自定义SQL功能,可以让我们利用Wrapper生成查询条件,再结合Mapper.xml编写SQL

基本用法

Service

@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);
}

Mapper

package com.itheima.mp.mapper;
​
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.mp.domain.po.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.Param;
​
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之中的用户 要是自己基于mybatis实现SQL,大概是这样的:

<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>

可以看出其中最复杂的就是WHERE条件的编写,如果业务复杂一些,这里的SQL会更变态。

但是基于自定义SQL结合Wrapper的玩法,我们就可以利用Wrapper来构建查询条件,然后手写SELECT及FROM部分,实现多表查询。

查询条件这样来构建:

@Test
void testCustomJoinWrapper() {
    // 1.准备自定义查询条件
    QueryWrapper<User> wrapper = new QueryWrapper<User>()
            .in("u.id", List.of(1L, 2L, 4L))
            .eq("a.city", "北京");
​
    // 2.调用mapper的自定义方法
    List<User> users = userMapper.queryUserByWrapper(wrapper);
​
    users.forEach(System.out::println);
}

然后在UserMapper中自定义方法:

@Select("SELECT u.* FROM user u INNER JOIN address a ON u.id = a.user_id ${ew.customSqlSegment}")
List<User> queryUserByWrapper(@Param("ew")QueryWrapper<User> wrapper);

当然,也可以在UserMapper.xml中写SQL:

<select id="queryUserByIdAndAddr" resultType="com.itheima.mp.domain.po.User">
    SELECT * FROM user u INNER JOIN address a ON u.id = a.user_id ${ew.customSqlSegment}
</select>

4-2.IService使用

4-1的查询数据库的方式相比Mybatis已经很方便了,至少不用再手写sql语句。

但是还可以更简便,我们可以直接在Controller接口层实现数据库的调用。

首先和4-1一样,需要提前准备Mapper、pojo、Service、ServiceImpl、Controller

改造Service层

public interface xxService extends IService<你的pojo> {
}

改造ServiceImpl层

@Service
public class xxServiceImpl extends ServiceImpl<你的Mapper, 你的pojo> implements xxService {
}

然后就可以在Controller使用了

新增

- save是新增单个元素
- saveBatch是批量新增
- saveOrUpdate是根据id判断,如果数据存在就更新,不存在则新增
- saveOrUpdateBatch是批量的新增或修改

删除

- removeById:根据id删除
- removeByIds:根据id批量删除
- removeByMap:根据Map中的键值对为条件删除
- remove(Wrapper<T>):根据Wrapper条件删除

修改

- updateById:根据id修改
- update(Wrapper<T>):根据UpdateWrapper修改,Wrapper中包含set和where部分
- update(T,Wrapper<T>):按照T内的数据修改与Wrapper匹配到的数据
- updateBatchById:根据id批量修改

查询

- getById:根据id查询1条数据
- getOne(Wrapper<T>):根据Wrapper查询1条数据
- getBaseMapper:获取Service内的BaseMapper实现,某些时候需要直接调用Mapper内的自定义SQL时可以用这个方法获取到Mapper

- listByIds:根据id批量查询
- list(Wrapper<T>):根据Wrapper条件查询多条数据
- list():查询所有

- count():统计所有数量
- count(Wrapper<T>):统计符合Wrapper条件的数据数量

到此这篇关于MyBatis无缝转MyBatis-plus的基本使用的文章就介绍到这了,更多相关MyBatis无缝转MyBatis-plus内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文