d41:MyBatisPlus入门,注解,配置,条件构造器,自定义SQL,IService

MyBatisPlus入门与实践指南

导航

  • 学习内容:MyBatisPlus入门,注解,配置,条件构造器,自定义SQL,IService

1. MyBatisPlus入门

MyBatisPlus(MP)是MyBatis的增强工具,提供了更便捷的CRUD操作。以下是入门步骤:

引入依赖

首先,在项目中引入MyBatisPlus的依赖:

xml 复制代码
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.1</version>
</dependency>

如果项目中已经使用了MyBatis,可以移除原有的MyBatis依赖。

继承MP的Mapper接口

创建一个Mapper接口,继承BaseMapper

java 复制代码
public interface UserMapper extends BaseMapper<User> {
}

这样就可以直接使用MP提供的CRUD方法,无需手动编写SQL语句。

示例代码
java 复制代码
@Test
void testSelectById() {
    User user = userMapper.queryUserById(5L);
    System.out.println("user = " + user);
}

注意 :如果定义了与BaseMapper方法同名的方法,BaseMapper的方法将被优先使用。


2. 常用注解和配置

MyBatisPlus通过实体类的反射来映射数据库表信息,支持多种注解和配置。

实体类注解
  • 指定表名

    java 复制代码
    @TableName("tb_user")
    public class User {
    }
  • 指定主键及其策略

    java 复制代码
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    • IdType.AUTO:自增ID
    • IdType.INPUT:手动输入
    • IdType.ASSIGN_ID:雪花算法(随机),也是默认策略
  • 指定字段名

    java 复制代码
    @TableField("username")
    private String username;
    • 布尔值字段,is前缀会被自动去除:

      java 复制代码
      @TableField("is_right")
      private Boolean isRight;
    • 避免与数据库的关键字段冲突:

      java 复制代码
      @TableField("`other`")
      private Integer other;
全局配置

MyBatisPlus支持MyBatis的原生配置,并提供了全局策略配置:

yaml 复制代码
mybatis-plus:
  mapper-locations: classpath*:mapper/**/*.xml
  type-aliases-package: com.itheima.mp.domain.po
  configuration:
    map-underscore-to-camel-case: true # 开启驼峰命名
    cache-enabled: false # 禁用二级缓存
  global-config:
    db-config:
      id-type: auto # 全局主键策略
      update-strategy: not_null # 默认更新策略

3. 条件构造器和自定义SQL

MyBatisPlus提供了强大的条件构造器,用于动态构造SQL语句。

QueryWrapper
java 复制代码
@Test
void testQueryWrapper() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<User>()
            .select("id", "username", "phone", "info", "balance")
            .like("username", "o")
            .ge("balance", 1000);
    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);
}
LambdaWrapper

通过反射获取字段名称,更加类型安全:

java 复制代码
@Test
void testLambdaWrapper() {
    LambdaQueryWrapper<User> queryWrapper = new QueryWrapper<User>()
            .lambda()
            .select(User::getId, User::getUsername, User::getPhone, User::getInfo, User::getBalance)
            .like(User::getUsername, "o")
            .ge(User::getBalance, 1000);
    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);
}
自定义SQL

可以直接编写SQL语句:

java 复制代码
@Test
void testUpdateWrapper() {
    List<Long> ids = List.of(1L, 2L, 4L);
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<User>()
            .setSql("balance = balance - 100")
            .in("id", ids);
    userMapper.update(null, updateWrapper);
}
条件比较函数
  • gt:大于(>
  • ge:大于等于(>=
  • lt:小于(<
  • le:小于等于(<=
  • eq:等于(=
  • ne:不等于(!=<>
条件构造器与Mapper混合使用
java 复制代码
@Test
void testCustomSql() {
    List<Long> ids = List.of(1L, 2L, 4L);
    int amount = 200;
    LambdaQueryWrapper<User> queryWrapper = new QueryWrapper<User>()
            .lambda()
            .in(User::getId, ids);
    userMapper.updateBalance(queryWrapper, amount);
}

注意 :构造器固定以"ew"为参数值:

java 复制代码
void updateBalance(@Param("ew") LambdaQueryWrapper<User> queryWrapper, int amount);

在Mapper XML中:

xml 复制代码
<update id="updateBalance">
    update user set balance = balance + #{amount}
    ${ew.customSqlSegment}
</update>

4. IService

通过IService进一步简化操作。

继承IService

在接口中继承IService

java 复制代码
public interface IUserService extends IService<User> {
}
实现类

实现类继承ServiceImpl

java 复制代码
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}
使用IService方法

可以直接使用IService的内置方法:

java 复制代码
@ApiOperation("新增用户")
@PostMapping
public void saveUser(@RequestBody UserFormDTO userFormDTO) {
    User user = BeanUtil.copyProperties(userFormDTO, User.class);
    userService.save(user);
}
业务处理

ServiceImpl中,可以直接使用IServiceMapper层的方法:

java 复制代码
public void deductBalance(Long id, Integer money) {
    User user = this.getById(id);
    baseMapper.deductBalance(id, money);
}

也可以使用Lambda构造业务逻辑:

java 复制代码
@Override
@Transactional
public void deductBalance(Long id, Integer money) {
    User user = this.getById(id);
    if (user == null || user.getStatus() == 2) {
        throw new RuntimeException("用户不存在或已冻结");
    }
    if (user.getBalance() < money) {
        throw new RuntimeException("余额不足");
    }
    int balance = user.getBalance() - money;
    lambdaUpdate()
            .set(User::getBalance, balance)
            .set(balance < 0, User::getStatus, 2)
            .eq(User::getId, id)
            .eq(User::getBalance, user.getBalance()) // 乐观锁
            .update();
}
Lambda查询
java 复制代码
@Override
public List<User> queryUsers(UserQuery userQuery) {
    String name = userQuery.getName();
    Integer status = userQuery.getStatus();
    Integer minBalance = userQuery.getMinBalance();
    Integer maxBalance = userQuery.getMaxBalance();
    return lambdaQuery()
            .like(name != null, User::getUsername, name)
            .eq(status != null, User::getStatus, status)
            .ge(minBalance != null, User::getBalance, minBalance)
            .le(maxBalance != null, User::getBalance, maxBalance)
            .list();
}

5. 批量操作

批量新增

采取分组发送的方式,避免通信传输和内存占用过大:

java 复制代码
@Test
void testSaveBatch() {
    List<User> list = new ArrayList<>(1000);
    long b = System.currentTimeMillis();
    for (int i = 1; i < 100000; i++) {
        list.add(buildUser(i));
        if (i % 1000 == 0) {
            userService.saveBatch(list);
            list.clear();
        }
    }
    long e = System.currentTimeMillis();
    System.out.println("耗时:" + (e - b));
}

注意 :尽管开启了批量保存,但MySQL默认会逐条插入。需要额外开启rewriteBatchedStatements=true


6. 小技巧

Lombok注解

使用Lombok的@RequiredArgsConstructor注解可以自动生成构造器,简化依赖注入:

java 复制代码
@RequiredArgsConstructor
public class UserController {
    private final IUserService userService;
}
相关推荐
w***42440 分钟前
SQL-Server链接服务器访问Oracle数据
服务器·sql·oracle
q***09802 小时前
MySQL 常用 SQL 语句大全
数据库·sql·mysql
q***64972 小时前
VS与SQL Sever(C语言操作数据库)
c语言·数据库·sql
BG8EQB3 小时前
开发者的存储救赎计划:从SQL到云原生的架构演进
sql·云原生·架构
♡喜欢做梦4 小时前
MyBatis XML 配置文件:从配置规范到 CRUD 开发实践
xml·java·java-ee·mybatis
百***757411 小时前
从 SQL 语句到数据库操作
数据库·sql·oracle
i***395811 小时前
SQL 注入详解:原理、危害与防范措施
数据库·sql·oracle
q***697712 小时前
Spring Boot与MyBatis
spring boot·后端·mybatis
舒一笑17 小时前
信息的建筑学:MyBatis Log Panda 如何重构开发者的认知地图
后端·sql·intellij idea
tanxiaomi18 小时前
Spring、Spring MVC 和 Spring Boot ,mybatis 相关面试题
java·开发语言·mybatis