一、通用 CRUD
1、提出问题:
假设我们已经存在一张 tbl_employee 表,且已经有对应的实体类 Employee,实现 tbl_employee 表的 CRUD 操作需要做什么呢?
2、实现方式:
基于 MyBatis:
① 需要编写 EmployeeMapper 接口,并手动编写CRUD 方法;
② 提供 EmployeeMapper.xml 映射文件,并手动编写每个方法对应的 SQL 语句;
基于 MP:
① 只需要创建 EmployeeMapper 接口,并继承 BaseMapper 接口,这就是使用 MP 需要完成的所有操作,甚至不需要创建 SQL 映射文件。
二、创建具体的 Mapper 接口
创建 Mapper 接口:
/**
* 基于MyBatis:在Mapper接口中编写CRUD相关的方法,提供mapper接口所对应的 SQL映射文件以及方法对应的SQL语句。
*
* 基于MP:让 XxxMapper 接口继承 BaseMapper 接口即可。
* BaseMapper<T> 泛型指定的就是当前Mapper接口所操作的实体类类型。
*
*/
public interface EmployeeMapper extends BaseMapper<Employee> {
}
三、BaseMapper 接口
BaseMapper 接口中定义了大量关于 CRUD 的方法,所以在具体的 Mapper 接口中不需要我们在定义方法:
四、insert 系列
1、insert 方法
测试代码:
/**
* 通用插入操作
*
* insert 方法在插入时,会根据实体类的每个属性进行非空判断,只有非空的属性对应的字段才会出现到 SQL语句中
*/
@Test
public void testCommonInsert() {
Employee emp = new Employee(null, "Smith", "Smith@126.com", 1, 19);
int i = employeeMapper.insert(emp);
System.out.println("i = " + i);
System.out.println(emp.getId());
}
运行报错了:
这是因为没有为实体类指定 id。
选择主键策略:
给id属性这是主键策略。
修改 JavaBean 的属性:
此时再运行:
还是报错了,报错信息为 mybatis_plus.employee 表不存在。
MP 在运行会根据类名去数据库中对应的表,如果找不到,就会报错。
我们可以使用 @TableName 注解,来指定数据库对应的表名:
再次运行:
可以看到运行成功了,也已经向数据库发送了 SQL 语句,当成功插入后,MP也会将主键值回写到实体类中,可以直接获取到插入后的 id 值。
支持主键值的数据库插入数据获取主键值:
MyBatis:需要通过 useGeneratedKeys 以及 keyProperty 来设置;
MP:自动将主键值回写到实体类中;
2、insertAllColumn
测试:
/**
* insertAllColumn 方法在插入时,不管属性是否非空,属性所对应的字段都会出现在SQL语句中
*/
@Test
public void testInsertAllColumn() {
Employee emp = new Employee();
emp.setLastName("Enma");
Integer r1 = employeeMapper.insertAllColumn(emp);
System.out.println("r1 = " + r1);
}
运行结果:
只会插入非空的属性值。
五、update 系列
1、update()
Demo:
/**
* 通用更新操作
* update:更新所有非空属性
* SQL 语句:
* Preparing: UPDATE tbl_employee SET email=?, age=? WHERE id=?
* Parameters: Tom@126.com(String), 23(Integer), 1(Integer)
*/
@Test
public void testCommonUpdate() {
Employee emp = new Employee();
emp.setId(1);
emp.setEmail("Tom@126.com");
emp.setAge(23);
//更新非空属性
Integer r1 = employeeMapper.updateById(emp);
System.out.println("r1 = " + r1);
}
2、updateAllColumnById()
Demo:
/**
* 通用更新操作
* updateAllColumnById:根据id更新所有的属性
* SQL 语句:
* Preparing: UPDATE tbl_employee SET last_name=?,email=?,gender=?,age=? WHERE id=?
* Parameters: null, Tom@126.com(String), null, null, 11(Integer)
*/
@Test
public void testCommonUpdateAllColumnById() {
Employee emp = new Employee();
emp.setId(11);
emp.setEmail("Tom@126.com");
Integer rs = employeeMapper.updateAllColumnById(emp);
System.out.println("rs = " + rs);
}
六、delete 系列
1、deleteById()
Demo:
/**
* 1.根据id删除
* SQL 语句:
* Preparing: DELETE FROM tbl_employee WHERE id=?
* Parameters: 11(Integer)
*/
@Test
public void testDeleteById() {
Integer r1 = employeeMapper.deleteById(11);
System.out.println("r1 = " + r1);
}
2、deleteBatchIds()
Demo:
/**
* 2.根据id批量删除
* SQL 语句:
* Preparing: DELETE FROM tbl_employee WHERE id IN ( ? , ? )
* Parameters: 10(Integer), 9(Integer)
*/
@Test
public void testDeleteBatchIds() {
Integer r1 = employeeMapper.deleteBatchIds(Arrays.asList(10, 9));
System.out.println("r1 = " + r1);
}
3、DeleteByMap()
Demo:
/**
* 3.根据条件进行删除 map的key需要是数据库的列名
* SQL 语句:
* Preparing: DELETE FROM tbl_employee WHERE gender = ? AND last_name = ? AND id = ?
* Parameters: 1(Integer), Smith(String), 8(Integer)
*/
@Test
public void testDeleteByMap() {
HashMap<String, Object> columnMap = new HashMap<String, Object>(){{
put("last_name", "Smith");
put("gender", 1);
put("id", 8);
}};
Integer r1 = employeeMapper.deleteByMap(columnMap);
System.out.println("r1 = " + r1);
}
七、select 系列
1、selectById()
Demo:
/**
* 1、通过id查询
* SQL语句:
* Preparing: SELECT id AS id,last_name AS lastName,email,gender,age FROM tbl_employee WHERE id=?
* Parameters: 1(Integer)
*/
@Test
public void testSelectById() {
Employee emp = employeeMapper.selectById(1);
System.out.println("emp = " + emp);
}
2、selectOne()
Demo:
/**
* 2、通过多个列进行查询 id + lastName selectOne只能查询一条记录
* SQL 语句:
* Preparing: SELECT id AS id,last_name AS lastName,email,gender,age FROM tbl_employee WHERE id=? AND last_name=? AND gender=?
* Parameters: 8(Integer), Smith(String), 1(Integer)
*/
@Test
public void testSelectOne() {
Employee employee = new Employee();
employee.setId(8);
employee.setLastName("Smith");
employee.setGender(1);
Employee emp = employeeMapper.selectOne(employee);
System.out.println("emp = " + emp);
}
注意:使用 selectOne() 方法必须要确保只能查询回来一条数据,如果查询多条就会报错。
3、selectBatchIds()
Demo:
/**
* 3.通过多个id进行批量查询
* SQL 语句:
* Preparing: SELECT id AS id,last_name AS lastName,email,gender,age FROM tbl_employee WHERE id IN ( ? , ? , ? )
* Parameters: 1(Integer), 2(Integer), 3(Integer)
*/
@Test
public void testBatchIds() {
List<Employee> emps = employeeMapper.selectBatchIds(Arrays.asList(1, 2, 3));
emps.forEach(System.out::println);
}
4、selectByMap()
Demo:
/**
* 4. 通过map封装条件查询,map中的key需要是数据库中的列名而不是JavaBean的属性名
* SQL 语句:
* Preparing: SELECT id AS id,last_name AS lastName,email,gender,age FROM tbl_employee WHERE gender = ? AND last_name = ?
* Parameters: 1(Integer), Smith(String
*/
@Test
public void testSelectByMap() {
HashMap<String, Object> columnMap = new HashMap<String, Object>(){{
put("last_name", "Smith");
put("gender", 1);
}};
List<Employee> emps = employeeMapper.selectByMap(columnMap);
emps.forEach(System.out::println);
}
5、selectPage()
Demo:
/**
* 5. 分页查询
*
* SQL语句:
* Preparing: SELECT id AS id,last_name AS lastName,email,gender,age FROM tbl_employee
* Parameters:
* 底层还是使用 RowBounds 实现,使用内存的分页方式
*/
@Test
public void testSelectPage() {
List<Employee> emps = employeeMapper.selectPage(new Page<>(2, 3), null);
emps.forEach(System.out::println);
}
Page 对象是我们用于设置分页辅助类,第一个参数为当前页码,第二个参数为要显示的行数。
Page 的继承树:
Page 是 RowBounds 的子类,是用于实现分页辅助类。
构造方法
八、通用 CRUD 总结
以上是基本的 CRUD 操作,在声明接口的时候仅仅需要继承一个 BaseMapper 即可实现大部分单表 CRUD 操作。BaseMapper 提供了多大 17个方法供我们使用,可以极其方便的实现单一、批量、分页等操作,极大的减少开发负担。
现在有一个需求,我们需要分页查询 Employee 表中,年龄在 18-50 之间性别为男且姓名为 xx 的所有用户,这时候该如何实现上述需求呢?》
MyBatis:需要在 SQL 映射文件中编写带条件查询的 SQL,并基于 PageHelper 插件完成分页,实现以上一个简单的需求,往往需要做很多重复单调工作。普通的 Mapper 能够解决这类痛点吗?
MP:依旧不用编写 SQL 语句,MP 提供了功能强大的条件构造器 EntityWrapper。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
2019-09-21 单链表 案例
2019-09-21 单链表