学习要求
良好的java基础, 熟悉SpringBoot框架,熟悉Mybatis框架
教程目标
1>了解并掌握MyBatis-Plus通用Mapper接口
2>掌握MyBatis-Plus 无sql CRUD操作
视频教程
BaseMapper介绍
mybatis-plus核心功能来自BaseMapper接口的实现
1>编写员工实体
@Setter
@Getter
@ToString
@TableName("employee")
public class Employee {
@TableId(value = "id", type= IdType.AUTO)
private Long id;
@TableField(value = "name", exist = true)
private String name;
private String password;
private String email;
private int age;
private int admin;
private Long deptId;
}
2>基本编写格式
public interface EmployeeMapper extends BaseMapper<Employee> {
}
3>BaseMapper方法集
insert:1个 update:2个 delete:4个 select:10个
BaseMapper--insert
mybatis-plus中添加方法有1个:
用法:传入要添加的实体对象
需求:往employee表中添加一条记录
@Test
public void testSave(){
Employee employee = new Employee();
employee.setAdmin(1);
employee.setAge(18);
employee.setDeptId(1L);
employee.setEmail("zhangsan@163.com");
employee.setName("zhangsan");
employee.setPassword("111");
employeeMapper.insert(employee);
}
执行后SQL
INSERT INTO employee ( id, name, password, email, age, admin, dept_id ) VALUES ( ?, ?, ?, ?, ?, ?, ? )
BaseMapper--update
mybatis-plus中更新方法有2个:
updateById
用法:以id作为更新条件更新指定实体对象
需求:更新id=1的员工信息
@Test
public void testUpdateById(){
Employee employee = new Employee();
employee.setId(1L);
employee.setAdmin(1);
employee.setAge(18);
employee.setDeptId(1L);
employee.setEmail("zhangsan@163.com");
employee.setName("zhangxiaosan");
employee.setPassword("111");
employeeMapper.updateById(employee);
}
执行后SQL
UPDATE employee SET name=?, password=?, email=?, age=?, admin=?, dept_id=? WHERE id=?
需求:更新id为1员工姓名为:zhangdasan
@Test
public void testUpdateById2(){
Employee employee = new Employee();
employee.setId(1L);
employee.setName("zhangdasan");
employeeMapper.updateById(employee);
}
执行后SQL
UPDATE employee SET name=?, age=?, admin=? WHERE id=?
执行之后就发现一个问题,employee表中id为1的员工数据age跟 admin这列数据丢失了,再看打印的SQL,本来只改name字段按理SQL中会拼接set name = ?但是SQL也拼接了age 跟admin列的更新 ,怎么回事呢?
这里就涉及到updateById使用注意要点了:
/**
* updateById 使用注意要点:
* 1>更新条件id
* 2>在拼接update语句中set片段时,根据传入实体对象某个属性值为不为null来判断是否拼接列
* 1:如果属性值为null, 不拼接, 如果属性值不为null, 那就拼接
* 2:如果属性是基本类型, 有默认值, mybatis-plus 默认拼接
*/
age 跟 admin 使用的int类型,mybatis-plus 默认拼接, 那该怎么解决
方案1:使用包装类型
private Integer age;
private Integer admin;
包装类型默认值为null, 不参与set拼接
方案2:使用update方法。
update
需求:更新id为1员工姓名为:zhangdasan
@Test
public void testUpdate2(){
//Wrapper :暂时认为是sql 语句中where
UpdateWrapper<Employee> wrapper = new UpdateWrapper<>();
wrapper.eq("id", 21L); //等价于: 拼接 where id = 21
wrapper.set("name", "zhangzhongsan");
employeeMapper.update(null, wrapper);
}
执行后SQL
UPDATE employee SET name=? WHERE (id = ?)
最后总结:
/**
* update跟updateById方法的选用
*
* 使用updateById 场景
* 1>where条件是id时候update场景
* 2>进行全量(所有字段)更新时候
*
* 使用update场景
* 1>where条件是不确定,或者多条件的update场景
* 2>进行部分字段更新时候
*/
BaseMapper--delete
mybatis-plus中删除方法有4个:
deleteById
用法:删除指定id的实体信息
需求:删除id为1的员工信息
@Test
public void testDeleteById(){
employeeMapper.deleteById(1L);
}
执行后SQL
DELETE FROM employee WHERE id=?
deleteBatchIds
用法:批量删除指定多个id对象信息
需求:删除id为1,2,3的员工信息
@Test
public void testDeleteBatchIds(){
employeeMapper.deleteBatchIds(Arrays.asList(1L, 2L, 3L));
}
执行后SQL
DELETE FROM employee WHERE id IN ( ? , ? , ? )
批量删除拼接的是in语法
deleteByMap
用法:按条件删除,具体条件放置在map集合中
需求:删除name=zhangsan并且age=18的员工信息
@Test
public void testDeleteByMap(){
//key: 列, value:要匹配的条件值
Map<String, Object> map = new HashMap<>();
map.put("name", "zhangsan");
map.put("age", 18);
//多条件删除, map里面装的都是where 条件
employeeMapper.deleteByMap(map);
}
执行后SQL
DELETE FROM employee WHERE name = ? AND age = ?
delete
用法:按条件删除,具体条件通过条件构造器拼接
需求:删除name=zhangsan并且age=18的员工信息
@Test
public void testDelete(){
//如果更新条件操作使用: UpdateWrapper
//其他条件操作使用: QueryWrapper
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.eq("age", 18);
wrapper.eq("name", "zhangsan"); //条件是and拼接
employeeMapper.delete(wrapper);
}
执行完的SQL
DELETE FROM employee WHERE (age = ? AND name = ?)
BaseMapper--select
mybatis-plus中查询方法有10个:
selectById
用法:查询指定id 对象信息
需求:查询id=1的员工信息
@Test
public void testselectById(){
Employee employee = employeeMapper.selectById(1L);
}
执行完SQL
SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE id=?
selectBatchIds
用法:批量查询指定的id对象信息
需求:查询id=1,2,3的员工信息
@Test
public void testselectBatchIds(){
employeeMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L));
}
执行完SQL
SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE id IN ( ? , ? , ? )
selectByMap
用法:查询满足条件实体信息,条件封装到map集合中
需求:查询age=18并且name=zhangsan的员工信息
@Test
public void testselectByMap(){
Map<String, Object> map = new HashMap<>();
map.put("age", 18);
map.put("name", "zhangsan");
List<Employee> employees = employeeMapper.selectByMap(map);
}
执行完SQL
SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE name = ? AND age = ?
selectCount
用法:查询满足条件实体信息记录总条数
需求:查询员工表记录条数
@Test
public void testselectCount(){
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
//如果统计所有数据:selectCount(null)
//Integer count = employeeMapper.selectCount(wrapper);
Integer count = employeeMapper.selectCount(wrapper);
}
执行完SQL
SELECT COUNT( 1 ) FROM employee
selectList
用法:查询满足条件实体信息记录, 返回List<T>
需求:查询满足条件的所有的员工信息, 返回List<Employee>
@Test
public void testselectList(){
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
List<Employee> list = employeeMapper.selectList(wrapper);
for (Employee employee : list) {
System.out.println(employee);
}
}
执行完SQL
SELECT id,name,password,email,age,admin,dept_id FROM employee
selectMaps
用法:查询满足条件实体信息记录, 返回List<Map<String, Object>>
需求:查询满足条件的所有的员工信息, 返回List<Employee>
@Test
public void testselectMaps(){
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
List<Map<String, Object>> mapList = employeeMapper.selectMaps(wrapper);
for (Map<String, Object> map : mapList) {
System.out.println(map);
}
}
执行完SQL
SELECT id,name,password,email,age,admin,dept_id FROM employee
思考:什么时候使用selectList,什么时候使用selectMaps
/**
* 如果sql语句执行完之后,得到的数据能封装成实体对象时使用:selectList
* 如果sql语句执行完之后,得到的数据不能封装成实体对象时使用:selectMaps
*/
selectPage
用法:分页查询满足条件实体信息记录
需求:查询第二页员工数据, 每页显示3条, (分页返回的数据是员工对象)
mybatis-plus分页查询步骤分2步:
1>在配置类中添加分页插件
//分页
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
paginationInnerInterceptor.setOverflow(true); //合理化
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
2>编写分页代码
@Test
public void testselectPage(){
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
//等价于:PageResult PageInfo
//参数1:当前页, 参数2:每页显示条数
Page<Employee> page = new Page<>(2,3);
Page<Employee> p = employeeMapper.selectPage(page, wrapper);
System.out.println(p == page); //true
System.out.println("当前页:" + page.getCurrent());
System.out.println("每页显示条数:" + page.getSize());
System.out.println("总页数:" + page.getPages());
System.out.println("总数:" + page.getTotal());
System.out.println("当前页数据:" + page.getRecords());
}
执行完SQL
SELECT COUNT(1) FROM employee
SELECT id,name,password,email,age,admin,dept_id FROM employee LIMIT ?,?
selectMapsPage
用法:跟selectPage一样,区别在与selectMapsPage返回分页数据集合泛型是Map, selectPage是实体对象。
selectOne
用法:查询满足条件实体对象,如果有多条数据返回,抛异常。
需求:查询name=zhangsan,password=1的员工数据
@Test
public void testselectOne(){
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.eq("name", "zhangsan");
wrapper.eq("password", "1");
Employee employee = employeeMapper.selectOne(wrapper);
System.out.println(employee);
}
执行完SQL
SELECT id,name,password,email,age,admin,dept_id FROM employee WHERE (name = ? AND password = ?)
selectObjs
用法:查询满足条件实体对象,返回指定列的集合,如果没有自定列,默认返回第一列
需求:查询员工表所有员工名称
@Test
public void testselectObjs(){
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.select("name");
List<Object> list = employeeMapper.selectObjs(wrapper);
list.forEach(System.out::println);
}
执行完SQL
SELECT name FROM employee
好了, 到这,通用的Mapper接口就介绍完了。