技术栈
技术类型 技术名称 数据源 HikariDataSource 数据库 h2/MySQL 8 数据持久化技术 MyBatis-Plus 3.5.2 Java后端框架 SpringBoot 2.7.5 代码编辑器 旗舰版 IDEA2022.2 依赖管理工具 Maven 3.6.3
1. 序言
1.1 MyBatis-Plus 的思维导图
1.2 MyBatis-Plus 的工作原理
2. 入门案例
2.1 创建数据库
2.1.1 设计数据表Usr表
id | name | age | |
---|---|---|---|
1 | Jone | 18 | [email protected] |
2 | Jack | 20 | [email protected] |
3 | Tom | 28 | [email protected] |
4 | Sandy | 21 | [email protected] |
5 | Billie | 24 | [email protected] |
2.1.2 数据库 Schema 脚本
DROP TABLE IF EXISTS user;
CREATE TABLE user
(
id INT NOT NULL COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
2.1.3 数据库 Data 脚本
DELETE FROM user;
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');
2.2 初始化 Spring Boot 过程
2.2.1 添加相关依赖
数据层技术=内置默认数据库H2
+数据持久层技术mybatis-plus
+内置的数据源HikariDataSource
<!--pom.xml配置-->
<!--数据持久化技术-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<!--jdbc规范,没有配置相关jdbc会报错(可以选择添加)-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--SpringBoot默认内置h2数据库(可以更换为其它类型的数据库)-->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--web,为了使用内置数据库h2的管理工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--使用junit相关API--->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
2.2.2 修改配置文件
# application.yml配置
## 配置数据源
spring:
datasource:
url: jdbc:h2:~/test
hikari:
username: sa
password: 123456
driver-class-name: org.h2.Driver
## h2相关配置
h2:
console:
### 开启h2管理工具
enabled: true
### 设置h2访问路径(http://localhost:端口/h2)
path: /h2
## 配置mybatis-plus
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl ### 开启日志
2.2.3 测试开发环境
步骤一:运行引导类Application.java
步骤二:在浏览器中输入:http://localhost:端口/h2,进入h2可是化管理工具。
步骤三:在h2可视化管理工具中执行相关SQL脚本
2.3 编码开发
2.3.1 编写实体类
package com.example.entity;
import lombok.Data;
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
2.3.2 编写 Mapper 接口
package com.example.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
小提示:
另外一种方法是在引导类前加个@MapperScanner 注解指定需要扫描的 Mapper 接口所在的包,就可以不在每个 Mapper 接口上加@Mapper 注解了。
若采用这种方法,IDEA 在 userMapper 处报错,因为找不到注入的对象,因为类是动态创建的,但是程序可以正确的执行。为了避免报错,可以在 mapper 接口上添加 @Repository 注解或者@Mapper 注解。
2.3.3 编写测试类
package com.example;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void testSelect() {
System.out.println(("----- selectAll method test ------"));
List<User> userList = userMapper.selectList(null);
Assert.assertEquals(5, userList.size());
userList.forEach(System.out::println);
}
}
2.3.4 控制台输出信息
----- selectAll method test ------ Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@544e6b] was not registered for synchronization because synchronization is not active JDBC Connection [HikariProxyConnection@393528546 wrapping conn0: url=jdbc:h2:~/test user=SA] will not be managed by Spring ==> Preparing: SELECT id,name,age,email FROM user ==> Parameters: <== Columns: ID, NAME, AGE, EMAIL <== Row: 1, Jone, 18, [email protected] <== Row: 2, Jack, 20, [email protected] <== Row: 3, Tom, 28, [email protected] <== Row: 4, Sandy, 21, [email protected] <== Row: 5, Billie, 24, [email protected] <== Total: 5 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@544e6b] User(id=1, name=Jone, age=18, [email protected]) User(id=2, name=Jack, age=20, [email protected]) User(id=3, name=Tom, age=28, [email protected]) User(id=4, name=Sandy, age=21, [email protected]) User(id=5, name=Billie, age=24, [email protected])
3. 基本 CRUD
3.1 BaseMapper接口
MyBatis-Plus 中的基本 CRUD 在内置的BaseMapper
中都已得到了实现,我们可以直接使用,接口如 下:
package com.baomidou.mybatisplus.core.mapper;
public interface BaseMapper<T> extends Mapper<T> {
/**
* 插入一条记录
* @param entity 实体对象
*/
int insert(T entity);
//____________________________________________delete____________________________________________________
/**
* 根据 ID 删除
* @param id 主键ID
*/
int deleteById(Serializable id);
/**
* 根据实体(ID)删除
* @param entity 实体对象
* @since 3.4.4
*/
int deleteById(T entity);
/**
* 根据 columnMap 条件,删除记录
* @param columnMap 表字段 map 对象
*/
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
/**
* 根据 entity 条件,删除记录
* @param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where
语句)
*/
int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 删除(根据ID 批量删除)
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
//____________________________________________update____________________________________________________
/**
* 根据 ID 修改
* @param entity 实体对象
*/
int updateById(@Param(Constants.ENTITY) T entity);
/**
* 根据 whereEntity 条件,更新记录
* @param entity 实体对象 (set 条件值,可以为 null)
* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成
where 语句)
*/
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
//____________________________________________select____________________________________________________
/**
* 根据 ID 查询
* @param id 主键ID
*/
T selectById(Serializable id);
/**
* 查询(根据ID 批量查询)
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
/**
* 查询(根据 columnMap 条件)
* @param columnMap 表字段 map 对象
*/
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object>columnMap);
//____________________________________________条件查询__________________________________________________
/**
* 根据 entity 条件,查询一条记录
* <p>查询一条记录,例如 qw.last("limit 1") 限制取一条记录, 注意:多条数据会报异常
</p>
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
default T selectOne(@Param(Constants.WRAPPER) 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");
}
return ts.get(0);
}
return null;
}
/**
* 根据 Wrapper 条件,查询总记录数
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
Long selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
* <p>注意: 只返回第一个字段的值</p>
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录(并翻页)
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
<P extends IPage<T>> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录(并翻页)
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类
*/
<P extends IPage<Map<String, Object>>> P selectMapsPage(P page,@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
}
3.2 插入
//添加
@Test
void testInsert(){
User user = new User();
user.setName("Helen");
user.setAge(18);
user.setEmail("[email protected]");
//INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
int result = userMapper.insert(user);
System.out.println(result);
//1475754982694199298
System.out.println(user);
}
注意:最终执行的结果,所获取的 id 为 1475754982694199298 这是因为 MyBatis-Plus 在实现插入数据时,会默认基于雪花算法的策略生成 id(详情参考:主键策略)
3.3 删除
3.3.1 通过 id 删除记录
@Test
void testDeleteById(){
//通过id删除用户信息
//DELETE FROM user WHERE id=?
int result = userMapper.deleteById(8L);
System.out.println(result);
}