我们先通过一个简单的Demo 来认识一下 MyBatis - Plus 的搭建和用法:
现在数据库中创建一张 User
表,表结构和数据如下
id | name | age | |
---|---|---|---|
1 | lx | 21 | 15831197211@163.com |
2 | cxuan | 20 | 15831197212@163.com |
3 | liux | 28 | 15831197213@163.com |
4 | xiaona | 21 | 15831197214@163.com |
5 | lxuan | 24 | 15831197215@163.com |
对应的建表语句和SQL语句如下
DROP TABLE IF EXISTS user;
CREATE TABLE user
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT(11) NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
INSERT INTO `user` VALUES (1, 'lx', 21, '15831197211@163.com');
INSERT INTO `user` VALUES (2, 'cxuan', 20, '15831197212@163.com');
INSERT INTO `user` VALUES (3, 'liux', 28, '15831197213@163.com');
INSERT INTO `user` VALUES (4, 'xiaona', 21, '15831197214@163.com');
INSERT INTO `user` VALUES (5, 'lxuan', 24, '15831197215@163.com');
使用 IDEA 新建一个 SpringBoot 项目,构建完成后,在 pom.xml
添加如下依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
</dependencies>
新建 application.yml
,在yml 文件上添加如下数据库驱动信息
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis
username: root
password: 123456
在主方法上添加 @MapperScan
注解,扫描mapper 包下面的内容
@SpringBootApplication
@MapperScan("com.mybatis.plus.mapper")
public class MybatisPlusApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusApplication.class, args);
}
}
新建一个 User
类,使用 @Data lombok 中的注解,如下
@Data
public class User {
private long id;
private String name;
private Integer age;
private String email;
}
然后新建一个接口,这个接口实现 BaseMapper
接口
public interface UserMapper extends BaseMapper<User> {}
使用单元测试进行测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MybatisPlusApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void contextLoads() {
System.out.println("----- selectAll method test -----");
List<User> userList = userMapper.selectList(null);
Assert.assertEquals(5,userList.size());
userList.forEach(System.out::println);
}
}
输出:
User(id=1, name=lx, age=21, email=15831197211@163.com) User(id=2, name=cxuan, age=20, email=15831197212@163.com) User(id=3, name=liux, age=28, email=15831197213@163.com) User(id=4, name=xiaona, age=21, email=15831197214@163.com) User(id=5, name=lxuan, age=24, email=15831197215@163.com)
通过以上几个简单的步骤,我们就实现了 User 表的 查询 功能,你没有看到一条 SQL 语句和 映射的编写。
从以上步骤中,我们可以看到集成MyBatis-Plus
非常的简单,只需要引入 starter 工程,并配置 mapper 扫描路径即可。
“说明:
Mybatis-Plus
启动时自动解析实体表关系映射转换为 Mybatis
内部对象注入容器T
为任意实体对象Serializable
为任意类型主键 Mybatis-Plus
不推荐使用复合主键约定,每一张表都有自己的唯一 id
主键Wrapper
为 条件构造器[2]看下其基本使用
insert 只有一种用法,直接插入对象的实体
/**
* 插入一条记录
* @param entity 实体对象
* @return 插入成功记录数
*/
int insert(T entity);
我们先为 User
实体类添加 @AllArgsConstructor
注解,如果 Lombok 不熟的同学请移步至 这些极简的注解你都清楚吗 这篇文章一探究竟。
下面是测试所用的代码
@Test
public void insertUserEntity(){
userMapper.insert(new User(6,"cxuanxuan",25,"15831197216@163.com"));
}
“注意 Junit 中测试的 insert 插入方法是没有返回值的,不然会报错,所以返回类型是void 。但其实 insert 方法是有返回值的,返回的是插入成功的记录数。
delete 有四种用法,分别是根据 id 删除、通过某个表字段删除、通过实体类删除和批量删除,比我们最初只是通过 id 删除功能强大很多。
/**
* 根据 ID 删除
* @param id 主键ID
* @return 删除成功记录数
*/
int deleteById(Serializable id);
/**
* 根据 columnMap 条件,删除记录
* @param columnMap 表字段 map 对象
* @return 删除成功记录数
*/
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
/**
* 根据 entity 条件,删除记录
* @param wrapper 实体对象封装操作类(可以为 null)
* @return 删除成功记录数
*/
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
/**
* 删除(根据ID 批量删除)
* @param idList 主键ID列表(不能为 null 以及 empty)
* @return 删除成功记录数
*/
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
验证示例如下:
// 根据某个特定的 id 进行删除。
@Test
public void deleteUserById(){
userMapper.deleteById(6);
}
// deleteByMap 参数是 Map<String, Object> 类型
// 第一个范型是字段名称,第二个范型是字段对应的值
@Test
public void deleteByColumnMap(){
Map<String,Object> columnMap = new HashMap<>();
columnMap.put("id",4);
userMapper.deleteByMap(columnMap);
}
// 使用 QueryWrapper 进行条件筛选
@Test
public void deleteEntity(){
QueryWrapper<User> queryWrapper = new QueryWrapper();
// 删除 name 不为 null ,并且 age 大于等于 28的记录
queryWrapper.isNotNull("name").ge("age",28);
userMapper.delete(queryWrapper);
}
// 根据 Collection 集合进行删除,也可以是 Collection 的子类
@Test
public void deleteBatch(){
List list = new ArrayList();
// 批量删除 1 和 2 的数据
list.add(1);
list.add(2);
userMapper.deleteBatchIds(list);
}
上面是 Delete 方法的测试例子,其中 **deleteByColumnMap 和 deleteEntity ** 方法如果不传任何值,默认删除表中所有的数据。deleteBatch
如果传递 null 的话,测试会报错,无法通过单元测试。
Update 更新方法只有两种形式,一种是直接根据 id 修改实体属性的值,一种是直接更新实体类
/**
* 根据 ID 修改
* @param entity 实体对象
* @return 修改成功记录数
*/
int updateById(@Param(Constants.ENTITY) T entity);
/**
* 根据 whereEntity 条件,更新记录
* @param entity 实体对象 (set 条件值,可为 null)
* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
* @return 修改成功记录数
*/
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
// 根据id更新User表
@Test
public void updateUserById(){
userMapper.updateById(new User(5,"cxuaner",25,"15831197216@163.com"));
}
// 更新 User 实体类信息
@Test
public void updateUserEntity(){
UpdateWrapper<User> updateWrapper = new UpdateWrapper();
updateWrapper.eq("age",28);
userMapper.update(new User(3,"cxuan",22,"15831197213@163.com"),updateWrapper);
}
UpdateWrapper
是一个条件构造器,测试的是 age 为 28 的这条记录进行更新。
条件构造器后面会进行更加详细的介绍。Select 用法比较多,现在来一起看一下Select 有哪些用法
/**
* 根据 ID 查询
* @param id 主键ID
* @return 实体
*/
T selectById(Serializable id);
/**
* 查询(根据ID 批量查询)
* @param idList 主键ID列表(不能为 null 以及 empty)
* @return 实体集合
*/
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
/**
* 查询(根据 columnMap 条件)
* @param columnMap 表字段 map 对象
* @return 实体集合
*/
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
/**
* 根据 entity 条件,查询一条记录
* @param queryWrapper 实体对象
* @return 实体
*/
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询总记录数
* @param queryWrapper 实体对象
* @return 满足条件记录数
*/
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录
* @param queryWrapper 实体对象封装操作类(可以为 null)
* @return 实体集合
*/
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
* @param queryWrapper 实体对象封装操作类(可以为 null)
* @return 字段映射对象 Map 集合
*/
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
* 注意:只返回第一个字段的值
* @param queryWrapper 实体对象封装操作类(可以为 null)
* @return 字段映射对象集合
*/
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录(并翻页)
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
* @return 实体分页对象
*/
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录(并翻页)
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类
* @return 字段映射对象 Map 分页对象
*/
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
下面就对上面的示例方法进行验证
/**
* 查询id = 1 的一条记录
*/
@Test
public void selectById(){
User user = userMapper.selectById(1);
System.out.println("user = " + user);
}
/**
* 批量查询id = 1,2,3 的记录
*/
@Test
public void selectUserBatchId(){
List batchIds = new ArrayList();
batchIds.add(1);
batchIds.add(2);
batchIds.add(3);
List list = userMapper.selectBatchIds(batchIds);
System.out.println("list = " + list);
}
/*
* 查询年龄为 21 岁的记录,并循环遍历输出
*/
@Test
public void selectUserByMap(){
Map<String,Object> userMap = new HashMap<>();
userMap.put("age",21);
List<User> users = userMapper.selectByMap(userMap);
users.forEach(p-> {
System.out.println(p);
});
}
/**
* 根据 entity 条件,查询一条id = 1 的记录,需要手动添加 User(long id)的构造器
*/
@Test
public void selectOneUser(){
// 需要在 User 类上添加一个 id 的构造函数
User user = userMapper.selectOne(new QueryWrapper<>(new User(1)));
System.out.println("user = " + user);
}
/**
* 根据 Wrapper 条件,查询年龄大于 22 的总条目数
*/
@Test
public void selectCountNum(){
QueryWrapper<User> queryWrapper = new QueryWrapper();
queryWrapper.ge("age",22);
Integer integer = userMapper.selectCount(queryWrapper);
System.out.println("查询出来的总记录数 = " + integer);
}
/*
* 查询年龄大于22 的所有记录数,返回一个List
*/
@Test
public void selectUserList(){
QueryWrapper<User> queryWrapper = new QueryWrapper();
queryWrapper.ge("age",22);
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(p-> {
System.out.println(p);
});
}
/*
* 查询年龄大于22 的所有记录数,返回的是一个List<Map>
*/
@Test
public void selectUserMaps(){
QueryWrapper<User> queryWrapper = new QueryWrapper();
queryWrapper.ge("age",22);
List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
maps.forEach(p-> {
System.out.println(p);
});
}
/**
* 查询年龄大于22 的所有记录数,返回的是一个List<Object>
* 注意:只返回第一个字段的值
*/
@Test
public void selectUserObject(){
QueryWrapper<User> queryWrapper = new QueryWrapper();
queryWrapper.ge("age",22);
List<Object> objects = userMapper.selectObjs(queryWrapper);
objects.forEach(p-> {
System.out.println(p);
});
}
[1]
BaseMapper: https://gitee.com/baomidou/mybatis-plus/blob/3.0/mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/mapper/BaseMapper.java
[2]
条件构造器: https://mp.baomidou.com/guide/wrapper.html