1. Mybatis-Plus概述
1.1 什么是Mybatis-Plus?
Mybatis-Plus(MP)是Mybatis的增强,在Mybatis的基础上不做改变只做增强,为简化开发、提高效率而生,尽可能的在开发过程中减少SQL语句的编写。
MyBatis-Plus 官方文档:https://mp.baomidou.com/
GitHub地址:https://github.com/baomidou/mybatis-plus
Gitee项目地址:https://gitee.com/baomidou/mybatis-plus
MyBatis-Plus开发组织:https://gitee.com/baomidou
1.2 Mybatis-Plus和Mybatis有什么区别?
Mybatis优点:
- SQL语句*控制,较为灵活
- SQL与业务代码分离,易于阅读与维护
- 提供动态SQL语句,可以根据需求灵活控制
Mybatis缺点:
- 简单的crud操作也必须提供对应SQL语句
- 必须维护大量的xml文件
- 自身功能有限,要拓展只能依赖第三方插件
Mybatis-Plus是在Mybatis的基础上进行加强,具有Mybatis的所有功能并拓展了独有的功能
Mybatis-Plus特点:
- 提供无SQL 的CRUD操作
- 内置代码生成器,分页插件, 性能分析插件等
- 提供功能丰富的条件构造器快速进行无SQL开发
1.3 Mybatis-Plus入门体验(集成SpringBoot)
本次数据库使用MySQL,开发工具为IDEA
1、 创建一张新表,导入初始数据
#建表语句
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`password` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`email` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`age` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
)
#导入初始数据
INSERT INTO `employee` VALUES (1, 'dayi', 'gfase345', 'dayi@1.com', 24);
INSERT INTO `employee` VALUES (2, 'geer', 'gs352', 'geer@2.com', 23);
INSERT INTO `employee` VALUES (3, 'zhangsan', 'ffafg4235', 'zhangsan@3.com', 21);
INSERT INTO `employee` VALUES (4, 'lisi', '5423fda', 'lisi@4.com', 24);
INSERT INTO `employee` VALUES (5, 'wangwu', 'dfaf543', 'wangwu@5.com', 24);
INSERT INTO `employee` VALUES (6, 'maliu', 'gag342', 'maliu@6.com', 32);
2、创建一个空的 Spring Boot 工程
可以选择Spring官方网页创建或者IDEA创建
3、导入本次项目的依赖
<!--Springboot父依赖-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
</dependencies>
4、在yml文件中添加数据库配置项
#mysql
spring :
datasource:
url: jdbc:mysql://localhost:3306/mp?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
username: root
password: admin
driver-class-name: com.mysql.cj.jdbc.Driver
5、创建实体类
@Setter
@Getter
@ToString
public class Employee {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private String password;
private String email;
private Integer age;
}
6、创建Mapper接口
继承BaseMapper接口,有一个泛型,填上对应需要操作的实体类
public interface EmployeeMapper extends BaseMapper<Employee> {
}
7、启动类中添加MapperScan注解扫描mapper包
需要保证Mapper接口能够被扫描到,这里采用了动态代理的方式对扫描到的Mapper接口进行代理,向spring容器中注入代理对象
@SpringBootApplication
@MapperScan(basePackages = "com.liuyipeng.mp.mapper")
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
8、添加测试类,进行功能测试
这里的selectList()方法的参数为MP内置的条件封装器Wrapper,所以不填写就是无条件
@SpringBootTest
public class EmployeeMapperTest {
@Autowired
private EmployeeMapper employeeMapper;
@Test
public void test(){
List<Employee> employees = employeeMapper.selectList(null);
employees.forEach(System.out::println);
}
}
控制台输出 :
Employee(id=1, name=dayi, password=gfase345, email=dayi@1.com, age=24)
Employee(id=2, name=geer, password=gs352, email=geer@2.com, age=23)
Employee(id=3, name=zhangsan, password=ffafg4235, email=zhangsan@3.com, age=21)
Employee(id=4, name=lisi, password=5423fda, email=lisi@4.com, age=24)
Employee(id=5, name=wangwu, password=dfaf543, email=wangwu@5.com, age=24)
Employee(id=6, name=maliu, password=gag342, email=maliu@6.com, age=32)
9、小结
通过上面8个步骤,我们就实现了Employee表的简单全表查询,不需要创建XML文件和编写SQL语句
也体验到了在Spring Boot工程下集成Mybatis Plus是多么的方便 ,只需要引入starter依赖,并配置Mapper扫描路径即可
2. 基本注解使用
注解文档 : https://baomidou.com/guide/annotation.html#tablename
@TableName
描 述 :表名注解
用 法 :贴在表对应实体类上
作 用 :通过value属性指定映射的表
其它属性 :略
@Tableld
描 述 :主键注解
用 法 :贴在主键对应的字段上
作 用 :通过value属性表示映射的主键列
其它属性 :略
@TableField
描 述 :字段注解(非主键)
用 法 :贴在字段上
作 用 :通过value属性表示当前映射表中哪一列,不贴默认属性名和列名一致
其它属性 :exist (false代表表中没有此列)
@Version
描 述 :乐观锁注解
用 法 :贴在字段上
作 用 :用于标记乐观锁操作字段
其它属性 :略
其它注解请自行查阅官方文档!
3. 通用Mapper接口(BaseMapper<T>)
解释 :
1、通用 CRUD 封装BaseMapper接口,为 Mybatis-Plus 启动时自动解析实体表关系映射转换为 Mybatis 内部对象注入容器
2、泛型 T 为任意实体对象
3、参数 Serializable 为任意类型主键 Mybatis-Plus 不推荐使用复合主键约定每一张表都有自己的唯一 id主键
4、对象 Wrapper 为条件构造器
Insert
源码:
/**
* 插入一条记录
*
* @param entity 实体对象
*/
int insert(T entity);
向数据库中添加一条数据:
@Test
public void testInsert(){
Employee employee = new Employee();
employee.setName("xiaoliu");
employee.setAge(18);
employee.setEmail("xiaoliu@q.com");
employee.setPassword("xiaoliu999");
employeeMapper.insert(employee);
}
只需封装好对应对象,调用通用Mapper接口中的方法即可快速的向数据库中添加一条数据
Update
1、根据 Id 更新
源码:
/**
* 根据 ID 修改
*
* @param entity 实体对象
*/
int updateById(@Param(Constants.ENTITY) T entity);
根据Id进行更新:
@Test
public void testUpdateById(){
Employee employee = employeeMapper.selectById(1L);
employee.setName("daliu");
employeeMapper.updateById(employee);
}
注意 : 如果我们实体类中某些字段使用的是基本数据类型,在创建对象时会有默认的值,导致在执行sql语句时,非null的的字段也进行了set拼接,就会导致表中有些数据为0的情况,这里步骤为先查询,再设置,再修改
2、根据条件构造器更新
源码:
/**
* 根据 whereEntity 条件,更新记录
*
* @param entity 实体对象 (set 条件值,可以为 null)
* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
根据条件构造器更新:
@Test
public void testUpdate() {
UpdateWrapper<Employee> wrapper = new UpdateWrapper<>();
wrapper.set("age",18);
wrapper.eq("name","xiaoliu");
employeeMapper.update(null,wrapper);
}
SQL:UPDATE employee SET age = ? WHERE (name = ?)
使用方式建议:
1、知道Id,并且所有更新用updateById
2、部分字段更新,用update ,通过wrapper构建条件
updateById : 全量更新, 只要传入对象属性不为null, 都可以进行update更新, 条件是通过id匹配
正确操作姿势: 前提: 必须知道id
1> 查
3> 更新
update+wrapper:部分字段更新, 通过wrapper对象拼接各种满足要求条件 , 更新set的列由wrapper 决定
正确操作姿势:
1> 设置更新条件
2> 拼接更新列
Delete
1、根据 ID 删除单条记录
源码:
/**
* 根据 ID 删除
*
* @param id 主键ID
*/
int deleteById(Serializable id);
根据 ID 删除:
@Test
public void testDeleteById() {
employeeMapper.deleteById(1L);
}
SQL : DELETE FROM employee WHERE id=?
2、根据 ID 批量删除
源码:
/**
* 删除(根据ID 批量删除)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
根据 ID 批量删除:
@Test
public void testDeleteBatchIds() {
employeeMapper.deleteBatchIds(Arrays.asList("2","3"));
}
SQL : DELETE FROM employee WHERE id IN ( ? , ? )
3、根据 Map 删除
源码:
/**
* 根据 columnMap 条件,删除记录
*
* @param columnMap 表字段 map 对象
*/
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
根据 Map 删除:
@Test
public void testDeleteByMap() {
Map<String, Object> map = new HashMap<>();
map.put("name","xaioliu");
map.put("age",18);
employeeMapper.deleteByMap(map);
}
SQL : DELETE FROM employee WHERE name = ? AND age = ?
4、根据 Wrapper 条件构造器删除
源码:
/**
* 根据 entity 条件,删除记录
*
* @param wrapper 实体对象封装操作类(可以为 null)
*/
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
根据 Wrapper 删除:
@Test
public void testDelete() {
UpdateWrapper<Employee> wrapper = new UpdateWrapper<>();
wrapper.eq("name","wangwu").eq("age",18);
employeeMapper.delete(wrapper);
}
SQL : DELETE FROM employee WHERE (name = ? AND age = ?)
Select
1、根据 ID 查询
源码:
/**
* 根据 ID 查询
*
* @param id 主键ID
*/
T selectById(Serializable id);
根据 ID 查询:
@Test
public void testSelectById() {
Employee employee = employeeMapper.selectById(5L);
System.out.println(employee);
}