MyBatis-Plus快速使用
1.介绍
MyBatis-Plus 是一个基于 MyBatis 的增强工具,旨在简化开发,提高效率。它在 MyBatis 的基础上进行扩展,只做增强不做改变,不会对现有的 MyBatis 构架产生任何影响。
特性和优势
-
无侵入性:MyBatis-Plus 在 MyBatis 的基础上进行扩展,只做增强不做改变,引入 MyBatis-Plus 不会对现有的 MyBatis 构架产生任何影响。
-
依赖少:仅仅依赖 MyBatis 以及 MyBatis-Spring。
-
性能损耗小:启动即会自动注入基本 CRUD,性能基本无损耗。
-
通用 CRUD 操作:内置通用 Mapper、通用 Service,仅需少量配置即可实现单表大部分 CRUD 操作。
-
多种主键策略:支持多达 4 种主键策略(内含分布式唯一 ID 生成器),可自由配置。
-
支持 ActiveRecord:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可实现基本 CRUD 操作。
-
代码生成:采用代码或者 Maven 插件可快速生成 Mapper、Model、Service、Controller 层代码。
-
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作。
-
内置性能分析插件:可输出 SQL 语句及其执行时间,建议开发测试时启用。
-
内置全局拦截插件:提供全表 delete、update 操作智能分析阻断,预防误操作。
2.快速使用
1.创建spingboot工程导入依赖
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-spring-boot3-starter</artifactId> <version>3.5.10.1</version> </dependency>
2.修改配置文件
#数据源 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/day1216 spring.datasource.username=root spring.datasource.password=123456 #日志 mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
3.创建实体类
@Data @TableName(value = "user")//如果类名与表名不同,使用该主机表示对应的表名 public class User { @TableId(value = "id")//该属性为主键列 private Integer id; @TableField(value = "name")//普通属性与列名不一致时 private String name; private Integer age; private String email; }
创建mapper接口
@Mapper//为该接口生成代理对象 public interface UserMapper extends BaseMapper<User> { }
测试
@SpringBootTest class DemoMp01ApplicationTests { @Autowired private UserMapper userMapper; @Test void contextLoads() { User user = userMapper.selectById(1); System.out.println(user); } }
3.主键生成策略
@TableId(value = "id",type = IdType.ASSIGN_ID)
IdType.AUTO
:使用数据库自增 ID 作为主键。IdType.NONE
:无特定生成策略,如果全局配置中有 IdType 相关的配置,则会跟随全局配置。IdType.INPUT
:在插入数据前,由用户自行设置主键值。IdType.ASSIGN_ID(默认)
:自动分配ID
,适用于Long
、Integer
、String
类型的主键。默认使用雪花算法通过IdentifierGenerator
的nextId
实现。@since 3.3.0
- 分布式集群项目
IdType.ASSIGN_UUID
:自动分配UUID
,适用于String
类型的主键。默认实现为IdentifierGenerator
的nextUUID
方法。@since 3.3.0
- 分布式 要求id必须是varchar类型
雪花算法(Snowflake Algorithm)是一种在分布式系统中生成唯一ID的方法
雪花算法的优点包括:
-
在高并发的分布式系统中,能够保证ID的唯一性。
-
基于时间戳,ID基本上是有序递增的。
-
不依赖于第三方库或中间件,减少了系统复杂性。
-
生成ID的效率非常高。
4.逻辑删除
- 删除:
update user set deleted=1 where id = 1 and deleted=0
- 查找:
select id,name,deleted from user where deleted=0
1.在数据库中增加一列逻辑列
2.创建实体类时,增加该列属性
3.在属性上加@TableLogic,表示是逻辑删除列
//批量删除 List<Integer> ids=new ArrayList<>(); ids.add(1); ids.add(2); ids.add(3); ids.add(4); userMapper.deleteBatchIds(ids);
5.修改时间,添加时间
1.在数据库里添加 修改时间列update_time,添加时间列create_time
2.修改实体类
@TableField(fill = FieldFill.INSERT) private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; @TableLogic//逻辑删除列 @TableField(fill = FieldFill.INSERT) private Integer deleted;
3.实现MetaObjectHandler
@Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); this.strictInsertFill(metaObject, "deleted", Integer.class,0); } @Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); } }
6.条件查询
@Test public void testFind(){ //Wrapper:mp把添加封装成该接口 查询条件 QueryWrapper<User> queryWrapper=new QueryWrapper<>(); queryWrapper.like("name", "小"); //or,不使用默认and queryWrapper.or(); //>= queryWrapper.ge("age",19); List<User> list = userMapper.selectList(queryWrapper); System.out.println(list); }
7.分页
分页配置类
import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MybatisPlusConfig { /** * 添加分页插件 */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 如果配置多个插件, 切记分页最后添加 // 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType return interceptor; } }
加依赖,版本与mybatis-plus对应
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-jsqlparser</artifactId> <version>3.5.10.1</version> </dependency>
测试
@Test public void testPage(){ // P page,分页对象 // @Param("ew") Wrapper<T> queryWrapper 条件对象 IPage<User> page=new Page<>(2,3); userMapper.selectPage(page,null); System.out.println("总条数"+page.getTotal()); System.out.println("总页码"+page.getPages()); System.out.println("当前页的记录"+page.getRecords()); }
8.联表分页
private Integer did; //部门对象,如果属性在数据库中不存在应该忽略该属性 @TableField(exist = false) private Dept dept;
@Data @TableName(value = "tbl_dept") @AllArgsConstructor @NoArgsConstructor public class Dept { @TableId private Integer id; @TableField(value = "dept_name") private String deptName; @TableField(value = "dept_loc") private String loc; }
public Page<User> findAll(Page page, @Param("ew") Wrapper<User> queryWrapper);
UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ghx.mapper.UserMapper"> <resultMap id="baseMapper" type="com.ghx.entity.User" autoMapping="true"> <id column="id" property="id"/> <association property="dept" javaType="com.ghx.entity.Dept"> <id column="dept_id" property="id"/> <result column="dept_name" property="deptName"/> <result column="dept_loc" property="loc"/> </association> </resultMap> <select id="findAll" resultMap="baseMapper"> select * from user u join tbl_dept d on u.did=d.dept_id where deleted=0 <if test="ew != null and ew.sqlSegment != ''"> AND ${ew.sqlSegment} </if> </select> </mapper>
测试
@Test public void testPage2(){ Page<User> page=new Page<>(2,3); QueryWrapper<User> queryWrapper=new QueryWrapper<>(); // queryWrapper.ge("age",20); userMapper.findAll(page,queryWrapper); System.out.println("总条数"+page.getTotal()); System.out.println("总页数"+page.getPages()); System.out.println("当前页的记录"+page.getRecords()); }