MybatisPlus

一、快速入门

1.1使用步骤

1.引入MybatisPlus的起步依赖

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

2.定义Mapper

自定义的Mapper继承MybatisPlus提供的BaseMapper接口:

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

3.在实体类上添加注解声明(可选)

4.在application.yml中根据需要添加配置(可选)

1.2常用注解

MyBatisPlus通过扫描实体类,并基于反射获取实体类信息作为数据库表信息。

@TableName:用来指定表名

@TableId:用来指定表中的主键字段信息

IdType枚举:

AUTO:数据库自增长

INPUT:通过set方法自行输入

ASSIGN_ID:分配ID,接口IdentifierGenerator的方法nextId来生成id,默认实现类为DefaultdentifierGenerator雪花算法

@TableField:用来指定表中的普通字段信息

成员变量名与数据库字段名不一致

成员变量名以is开头,且是布尔值

成员变量名与数据库关键字冲突

成员变量不是数据库字段

java 复制代码
@TableName("tb_user")
public class User{
    @TableId(value="id",type=IdType.AUTO)
    private Long id;
    @TableField("username")
    private String name;
    @TableField("is_married")
    private Boolean isMarried;
    @TableField("`order`")//转义字符
    private Integer order;
    @TableField(exist = false)
    private String address;
}

1.3常用配置

MyBatisPlus的配置项继承了MyBatis原生配置和一些自己特有的配置。例如:

bash 复制代码
mybatis-plus:
    type-aliases-package: com.cake.mp.domain.po #别名扫描包
    mapper_locations: "classpath*:/mapper/**/*.xml" #Mapper.xml文件地址,默认值
    configuration:
        map-underscore-to-camel-case: true #是否开启下划线和驼峰映射
        cache-enabled: false #是否开启二级缓存
    global-config:
        db-config:
            id-type: assign_id #id为雪花算法生成
            update_strategy: not_null #更新策略:只更新非空字段

官网:https://www.baomidou.com

二、核心功能

2.1条件构造器

MyBatisPlus支持各种复杂的where条件,可以满足日常开发的所有需求。

示例:

1.查询出名字中带o的,存款大于等于1000元的人的id、username、info、balance字段

数据库语句:

sql 复制代码
SELECT id,username,info,balance FROM user WHERE username LIKE ? AND balance >= ?

MyBatisPlus实现:

java 复制代码
@Test
void testQueryWrapper(){
    //1.构建查询条件    
    QueryWrepper<User> wrapper = new QueryWrapper<User>()
            .select("id","username","info","balance")
            .like("username","o")
            .ge("balance",1000);//gt是大于,ge是大于等于
                
    //2.查询
    userMapper.selectList(wrapper);
}

使用Lambda

java 复制代码
@Test
void testQueryWrapper(){
    //1.构建查询条件    
    LambdaQueryWrepper<User> wrapper = new LambdaQueryWrapper<User>()
            .select(User::getId,User::getUsername,User::getInfo,User::getBalance)
            .like(User::getUsername,"o")
            .ge(User::getBalance,1000);//gt是大于,ge是大于等于
                
    //2.查询
    userMapper.selectList(wrapper);
}

2.更新用户名为jack的用户的余额为2000

数据库语句:

sql 复制代码
UPDATE user SET balance = 2000 WHERE (username = "jack")

MyBatisPlus实现:

java 复制代码
@Test
void testUpdateByQueryWrapper(){
//1.要更新的数据
User user = new User();
user.setBalance(2000);
//2.更新条件
QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username","jack");
//3.执行更新
userMapper.update(user,wrapper);
}

3.更新id为1,2,4的用户的余额,扣200

数据库语句:

sql 复制代码
UPDATE user SET balance = balance - 200 WHERE id in (1,2,4)

MyBatisPlus实现:

java 复制代码
@Test 
void testUpdateWrapper(){
    List<Long> ids = List.of(1L,2L,4L);
    UpdateWrapper<User> wrapper = new UpdateWrapper<User>()
            .setSql("balance = balance - 200")
            .in("id",ids);
    userMapper.update(null,wrapper);
}

小结

条件构造器的用法:

QueryWrapper和LambdaQueryWrapper通常用来构建select,delete,update的where条件部分。

UpdateWrapper和LambdaUpdateWrapper通常只有在set语句比较特殊才使用。

尽量使用LambdaQueryWrapper和LambdaUpdateWrapper,避免硬编码。

2.2自定义SQL

可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,然后自己定义SQL语句中剩下的部分

示例:将id在指定范围的用户(例如:1,2,4)的余额扣减指定值

1.基于Wrapper构建where条件

java 复制代码
List<Long> ids = List.of(1L,2L,4L);
int amount = 200;
//1.构建条件
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>().in(User::getId,ids);
//2.自定义SQL方法调用
userMapper.updateBalanceByIds(wrapper,amount);

2.在mapper方法参数中用Param注解声明wrapper变量名称,必须是ew

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

3.自定义SQL,并使用Wrapper条件

XML 复制代码
<update id="updateBalanceByIds">
    UPDATE tb_user SET balance = balance - #{amount} ${ew.customSqlSegment}
</update>

2.3Service接口

2.3.1 IService接口基本用法

接口

java 复制代码
public interface IUserService extends IService<User>{

}

实现类

java 复制代码
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService{
    

}

2.3.2 IService的Lambda方法

IService的Lambda查询

java 复制代码
@Override
public List<User> queryUsers(String name,Integer status,Integer minBalance,Integer maxBalance){
    List<User> users = lambdaQuery()
            .like(name != null,User::getUsername,name)
            .eq(status != null,User::getStatus,status)
            .gt(minBalance != null,User::getMinBalance,minBalance)
            .lt(maxBalance != null,User::getMaxBalance,maxBalance)
            .list();
    return users;

IService的Lambda更新

java 复制代码
@Override
@Transactional
public void deductBalance(Long id,Integer money){
    //1.查询用户
    User user = getById(id);
    //2.校验用户状态
    if(user == null || user.getStatus() == 2){
        throw new RuntimeException("用户状态异常!");
    }
    //3.校验余额是否充足
    if (user.getBalance() < money){
        throw new RuntimeException("用户余额不足!");
    }
    //4.扣减余额
    int remainBalance = user.getBalance() - money;
    lambdaUpdate()
        .set(User::getBalance,remainBalance)
        .set(remainBalance == 0,User::getStatus,2)//status=2 账户冻结
        .eq(User::getId,id)
        .eq(User::getBalance,user.getBalance())// 乐观锁
        .update();
}

2.3.3 IService批量新增

在.yml配置文件的 spring: datasource: url: ......&rewriteBatchedStatements=true<--加这一句

java 复制代码
@Test
void testSaveBatch(){
    //1.准备一个容量为1000的集合
    List<User> list = new ArrayList<>(1000);
    long b = System.currentTimeMillis();
    for (int i = 1;i<=100000;i++){
        //2.添加一个user
        list.add(buildUser(i));
        //3.每1000条批量插入一次
        if (i % 1000 == 0){
             userService.saveBatch(list);
            //4.清空集合,准备下一批数据
            list.clear();
        }    
    }
    long e = System.currentTimeMillis();
    System.out.printLn("耗时:"+(e - b));
}

批处理方案:

-普通for循环逐条插入速度极差,不推荐

-MP的批量新增,基于预编译的批处理,性能不错

-配置jdbc参数,开rewriteBatchedStatements,性能最好

相关推荐
SunnyDays10112 小时前
使用 Java 提取和删除 PDF 文档附件(完整指南)
java·pdf
Stack Piston2 小时前
Spring实践@Cacheable坑
java·后端·spring
二宝1522 小时前
互联网大厂Java面试实战演练:谢飞机的三轮提问与深入解析
java·spring boot·redis·微服务·面试·kafka·oauth2
陌上花开zz2 小时前
Spring Boot整合EasyExcel,动态导出表头和数据
java·spring boot·easyexcel·动态导出
MicoZone2 小时前
源码-redisson
java
happymaker06262 小时前
请求头 & 文件下载 & JSP 内置对象实战
java·前端·servlet
Cosmoshhhyyy2 小时前
《Effective Java》解读第46条:优先选择Stream中无副作用的函数
java·windows·python
无籽西瓜a2 小时前
【西瓜带你学设计模式 | 第十一期 - 模板方法模式】模板方法模式 —— 流程骨架与钩子实现、优缺点与适用场景
java·后端·设计模式·软件工程·模板方法模式
九皇叔叔2 小时前
005-SpringSecurity-Demo 配置外部文件映射
java·springboot·文件·springsecurity