一、快速入门
1.引入MybatisPlus的起步依赖
mybatisPlus官方提供了starter。其中集成了Mybatis和MybatisPlus的所有功能,对mybatis实现了润物无声,并且实现了自动装配效果。
因此使用了Mybatis的项目,也可以使用MybatisPlus的starter代替Mybatis的starter:
<!-- mybatisplus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
2.定义Mapper
自定义的 Mapper继承MybatisPlus提供的BaseMapper接口:
package com.lql.race.mapper;
import com.lql.race.model.dto.AdminDto;
import com.lql.race.model.po.Admin;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lql.race.model.vo.AdminVo;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author 李大爷
* @since 2024-10-09
*/
public interface AdminMapper extends BaseMapper<Admin> {
Admin login(Admin admin);
@Select("select id from admin where id = #{id} and password = #{password}")
Admin findPwd(Admin admin);
}
3.常见注解
MybatisPlus通过扫描实体类,并基于反射获取实体类信息作为数据库表信息。
package com.lql.race.model.po;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* <p>
*
* </p>
*
* @author 李大爷
* @since 2024-10-09
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("admin")
@ApiModel(value="Admin对象", description="")
public class Admin implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String account;
private String password;
private String phone;
private Integer type;
private Integer adminid;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date regTime;
}
类名驼峰转下划线作为表名
变量名驼峰转下划线作为表的字段名
自定义配置:
如果不符合MybatisPlus的约定就要使用自定义配置。
@TableName:用来指定表名
@TableId:用来指定主键
@TableField:用来指定表中对应的字段
使用TableField的常见场景:
1)成员变量名与数据库字段名不一致
2)成员变量名以is开头,且是布尔值(经过反射处理,它会将is去掉作为数据库字段名)
3)成员变量名与数据库关键字冲突
4)成员变量名不是数据库字段(数据库中不存在该字段)
4.常用配置
mybatis-plus:
type-aliases-package: com.lql.race.po
mapper-locations: classpath:mapper/*Mapper.xml
global-config:
db-config:
id-type: auto
update-strategy: not_null
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
map-underscore-to-camel-case: true
cache-enabled: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
二、核心功能
5.条件构造器
QueryWrapper和LambdaQueryWrapper通常用来构建select、delete、update的where条件部分
UpdateWrapper和LambdaUpdateWrapper通常只有在set语句比较特殊才使用
尽量使用LambdaQueryWrapper和LambdaUpdateWrapper,避免硬编码
6.自定义sql
我们可以利用MybatisPlus的Wrapper来构建复杂的where条件,然后自己定义sql语句中剩下的部分。
7.IService接口
1)IService接口使用流程:
自定义Service接口继承IService并指定实体类泛型
package com.lql.race.service;
import com.lql.race.model.dto.AdminDto;
import com.lql.race.model.po.Admin;
import com.baomidou.mybatisplus.extension.service.IService;
import com.lql.race.model.query.AdminQuery;
import com.lql.race.model.vo.AdminVo;
import com.lql.race.model.vo.Result;
import java.util.List;
/**
* <p>
* 服务类
* </p>
*
* @author 李大爷
* @since 2024-10-09
*
* 批处理新增 删除
*
* 使用service接口和实现类的目的:
* 1.解耦
* 2.多态
* 3.
*/
public interface IAdminService extends IService<Admin> {
Result login(Admin admin);
List<AdminVo> adminList();
Result findAdminById(Integer id);
List<AdminVo> adminList1(AdminDto adminDto);
Result findPwd(AdminDto adminDto);
void updatee(AdminDto adminDto);
Admin getAdminByAccount(String account);
Result adminPage(AdminQuery adminDto);
}
2)Lambda
IService中还提供了Lambda功能来简化我们的复杂查询及更新功能。
@Override
public List<User> queryUsers(UserQuery userQuery) {
return lambdaQuery()
.like(userQuery.getName() != null, User::getUsername, userQuery.getName())
.eq(userQuery.getStatus() != null, User::getStatus, userQuery.getStatus())
.ge(userQuery.getMinBalance() != null, User::getBalance, userQuery.getMinBalance())
.le(userQuery.getMaxBalance() != null, User::getBalance, userQuery.getMaxBalance())
.list();
}
3)批量新增
用for循环非常慢,需要使用MybatisPlus的批处理:
@Test
void testSaveBatch() {
// 准备10万条数据
List<User> list = new ArrayList<>(1000);
long b = System.currentTimeMillis();
for (int i = 1; i <= 100000; i++) {
list.add(buildUser(i));
// 每1000条批量插入一次
if (i % 1000 == 0) {
userService.saveBatch(list);
list.clear();
}
}
long e = System.currentTimeMillis();
System.out.println("耗时:" + (e - b));
}
根据MybatisPlus源码显示,MybatisPlus的批处理是基于PrepareStatement
的预编译模式,然后批量提交,最终在数据库执行时还是会有多条insert语句,逐条插入数据。而想得到最佳性能,最好是将多条SQL合并为一条。
MySQL的客户端连接参数中有这样的一个参数:rewriteBatchedStatements。顾名思义,就是重写批处理的statement语句。这个参数的默认值是false,我们需要修改连接参数,将其配置为true。
在配置文件中,在数据库连接配置中在url后面加上 rewriteBatchedStatements=true 的一个参数:
url: jdbc:mysql://192.168.44.128:3306/race?serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
在ClientPreparedStatement
的executeBatchInternal
中,有判断rewriteBatchedStatements
值是否为true并重写SQL的功能,这样效率就有了明显的提升。
三、扩展功能
1.代码生成器
(1)安装插件
下载idea插件并apply,帮助实现代码生成
(2) 使用
配置数据库信息
dbUrl的填写直接复制application中的数据库配置中的url即可:
2.Db静态工具
有的时候Service之间也会相互调用,为了避免出现循环依赖问题,MybatisPlus提供一个静态工具类:Db
,其中的一些静态方法与IService
中方法签名基本一致,也可以帮助我们实现CRUD功能:
Db静态工具由MybatisPlus提供,直接使用就可以;hutool工具提供的Db我没有用过,这里示例代码使用MybatisPlus提供的Db
@GetMapping(path = "/deleteadmin")
public Result deleteAdmin(@Param("id") Integer id) {
adminService.removeById(id);
Db.lambdaUpdate(AdminMenu.class).eq(AdminMenu::getAdminid, id).remove();
// adminMenuService.delete(id);//删除该管理员权限
return new Result(200, "delete success", null);
}
Db静态工具在Service层和Controller层都可以使用
@Override
public void saveAttractionType(Integer[] typeIds, int id) {
for (Integer typeId : typeIds) {
AttractionAttractiontype attractionAttractiontype = new AttractionAttractiontype();
attractionAttractiontype.setAttractionId(id);
attractionAttractiontype.setAttractionTypeId(typeId);
Db.save(attractionAttractiontype);
}
}