MyBatis-Plus(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
mybatis 、mybatis-plus 二者区别:
MyBatis:
- 所有SQL语句全部自己写
- 手动解析实体关系映射转换为MyBatis内部对象注入容器
- 不支持Lambda形式调用
Mybatis Plus:
- 强大的条件构造器,满足各类使用需求
- 内置的Mapper,通用的Service,少量配置即可实现单表大部分CRUD操作
- 支持Lambda形式调用
- 提供了基本的CRUD功能,连SQL语句都不需要编写
- 自动解析实体关系映射转换为MyBatis内部对象注入容器
一、什么是MybatisPlus
MybatisPlus可以节省大量时间,所有的CRUD代码都可以自动化完成
MyBatis-Plus是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特性:
-
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
-
损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
-
强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
-
支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
-
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
-
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
-
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
-
内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
-
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
-
分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
-
内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
-
内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
二、快速入门
1、准备数据库:
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '姓名',
`job` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '工作',
`salary` double NULL DEFAULT NULL COMMENT '工资',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
`deleted` bigint(0) NULL DEFAULT 0 COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 191 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, '张三', '随便', 2000, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
INSERT INTO `user` VALUES (2, '李四', '程序员', 2800, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
INSERT INTO `user` VALUES (3, '王五', '程序员鼓励师', 2700, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
INSERT INTO `user` VALUES (4, '王二', '部门总监', 4200, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
INSERT INTO `user` VALUES (5, '麻子', '程序员', 3000, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
INSERT INTO `user` VALUES (6, '最帅三太子', '程序员', 3500, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
INSERT INTO `user` VALUES (7, '苍老师', '程序员', 3700, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
INSERT INTO `user` VALUES (8, '波多野结衣', 'CEO', 5000, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
INSERT INTO `user` VALUES (9, '测试3', '测试工作3', 500, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
2、创建项目 略
3、引入依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.14</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId><!---->
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>1.18.22</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!-- mybatis plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
</dependencies>
4、添加配置:
spring:
datasource:
url: jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
transaction-isolation: 2 #具体定义可在Transactional->Isolation属性查看
#hikari数据库连接池
hikari:
pool-name: Retail_HikariCP
minimum-idle: 1 #最小空闲连接数量
idle-timeout: 180000 #空闲连接存活最大时间,默认600000(10分钟)
maximum-pool-size: 10 #连接池最大连接数,默认是10
auto-commit: true #此属性控制从池返回的连接的默认自动提交行为,默认值:true
max-lifetime: 1800000 #此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
connection-timeout: 30000 #数据库连接超时时间,默认30秒,即30000
在spring boot启动类中添加@MapperScan注解,扫描Dao文件夹:
@SpringBootApplication
@MapperScan("com.test.demo.dao")
public class TESTApplication {
public static void main(String[] args) {
SpringApplication.run(TESTApplication.class,args);
}
}
5、编码:
@Getter
@Setter
@ToString(callSuper = true)
@Accessors(chain = true)
@TableName("user")
public class User {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Integer id;
private String name;
private String type;
private String job;
private Double salary;
private LocalDateTime createTime;
private LocalDateTime updateTime;
private Long deleted;
}
编写Mapper包下的Dao接口
//再对应的mapper上面实现基本的接口 BaseMapper
@Mapper
public interface UserDao extends BaseMapper<User> {
//所有的CRUD都已经完成
//不需要像以前一样配置一大堆文件:pojo-dao(连接mybatis,配置mapper.xml文件)==>service-controller
}
注意:
要在主启动类上去扫描mapper包下的所有接口:@MapperScan("com.test.demo.dao")
6、简单使用
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserDao userDao;
@GetMapping("/get/{id}")
public User findAll(@PathVariable("id") int id ){
return userDao.selectById(id);
}
}
三、增删改查
上面说我们dao接口继承了BaseMapper之后,基本的crud方法就可以直接使用了,就像举例中的 userDao.selectById(id) 方法一样,我们在 userDao 中并没有写 selectById() 方法,但是继承了BaseMapper之后就可以直接用了。这是因为BaseMapper已经帮我们写好了基本的crud方法,可以简单看一下源码:
public interface BaseMapper<T> extends Mapper<T> {
int insert(T entity);
int deleteById(Serializable id);
int deleteById(T entity);
int deleteByMap(@Param("cm") Map<String, Object> columnMap);
int delete(@Param("ew") Wrapper<T> queryWrapper);
int deleteBatchIds(@Param("coll") Collection<?> idList);
int updateById(@Param("et") T entity);
int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);
T selectById(Serializable id);
List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);
List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
default T selectOne(@Param("ew") Wrapper<T> queryWrapper) {
List<T> ts = this.selectList(queryWrapper);
if (CollectionUtils.isNotEmpty(ts)) {
if (ts.size() != 1) {
throw ExceptionUtils.mpe("One record is expected, but the query result is multiple records", new Object[0]);
} else {
return ts.get(0);
}
} else {
return null;
}
}
default boolean exists(Wrapper<T> queryWrapper) {
Long count = this.selectCount(queryWrapper);
return null != count && count > 0L;
}
Long selectCount(@Param("ew") Wrapper<T> queryWrapper);
List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);
List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);
List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);
<P extends IPage<T>> P selectPage(P page, @Param("ew") Wrapper<T> queryWrapper);
<P extends IPage<Map<String, Object>>> P selectMapsPage(P page, @Param("ew") Wrapper<T> queryWrapper);
}
上面的所有方法其实都比较容易理解,insert、delect、update、select开头的方法分别对应着增删改查,page方法代表着分页查询。
上面的方法涵盖了单表查询的基本方法,所以如果不是复杂sql的,我们直接直接使用现成的方法进行查询。下面对各个方法做一个简单演示。
1、insert
User user = new User();
user.setName("测试1");
user.setJob("测试工作");
userDao.insert(user);
说到增加,就得提一下主键的生成策略,在mybatis中主键的生成策略需要配合标签或者注解中的属性来设置。在mybatisplus中主键的生成策略可以通过 @TableId() 注解来设置。这个注解是直接加载主键字段上面的。例如User类中:
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
上面这个设置代表的是,id字段对应数据库字段为id,且为主键。 type = IdType.ASSIGN_ID 代表 基于雪花算法的策略生成数据id。我们执行两次保存操作后,会发现数据自动填充了id:
type 也可以设置为 IdType.AUTO ,代表:使用数据库的自增策略,注意:该类型需确保数据库设置了自增id,否则无效。
加上这个注解之后,不需要再加任何配置,就可以生成主键id,这对于我们操作来说变得非常方便。至于其中的原理会放在后面说。
还有一个注解顺便提一下:@TableId ,这个注解主要是解决属性所对应字段不一致的情况,比如说当user实体类中的name 属性命名的是 userName ,但是数据库中命名的是 name 这样不一致,查询就无法映射到对应字段,可以加上这个注解代表这两个字段是同一个:
@TableField("name")
private String userName;