一、通用Mapper接口扩展
1、说明
这里的扩展是指增加通用Mapper提供的功能。
2、举例
通用Mapper官方文档中使用一个批量 insert 作为扩展功能的例子:
tk.mybatis.mapper.additional.insert.InsertListMapper<T>
tk.mybatis.mapper.additional.insert.InsertListProvider
我们来仿照写一个批量 update,假设我们想生成下面这样的 SQL 语句:
update table_emp set emp_name=?, emp_age=?,emp_salary=? where emp_id=?;
update table_emp set emp_name=?, emp_age=?,emp_salary=? where emp_id=?;
update table_emp set emp_name=?, emp_age=?,emp_salary=? where emp_id=?;
......
为了生成上面那样的 SQL 语句,我们需要使用到 MyBatis 的 foreach 标签:
<foreach collection="list" item="record" separator=";">
UPDATE table_emp
SET emp_name=#{record.empName},
emp_age=#{record.empAge},
emp_salary=#{record.empSalary},
where emp_id=#{record.empId}
<foreach>
3、需要提供的接口和实现类

二、扩展Mapper接口
1、创建扩展接口与实现类
接口:
public interface MyBatchUpdateMapper<T> {
@UpdateProvider(type= MyBatchUpdateProvider.class, method = "dynamicSQL")
public void batchUpdate(List<T> list);
}
实现类:
public class MyBatchUpdateProvider extends MapperTemplate {
public MyBatchUpdateProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
super(mapperClass, mapperHelper);
}
public String batchUpdate(MappedStatement ms) {
return null;
}
}
2、方法类的实现(拼接SQL)
public class MyBatchUpdateProvider extends MapperTemplate {
public MyBatchUpdateProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
super(mapperClass, mapperHelper);
}
/*
<foreach collection="list" item="record" separator=";">
UPDATE tabple_emp
<set>
emp_name=#{record.empName},
emp_age=#{record.empAge},
emp_salary=#{record.empSalary}
</set>
where emp_id=#{record.empId}
</foreach>
*/
public String batchUpdate(MappedStatement ms) {
//1.创建StringBuilder用于拼接SQL语句的各个组成部分
StringBuilder builder = new StringBuilder();
//2.拼接foreach标签
builder.append("<foreach collection=\"list\" item=\"record\" separator=\";\">");
//3.获取实体类对应的Class对象
Class<?> entityClass = super.getEntityClass(ms);
//4.获取实体类在数据库中对应的表名
String tableName = super.tableName(entityClass);
//5.生成update子句
String updateClause = SqlHelper.updateTable(entityClass, tableName);
builder.append(updateClause);
builder.append("<set>");
//6.获取所有字段信息
Set<EntityColumn> columns = EntityHelper.getColumns(entityClass);
String idColumn = null;
String idHolder = null;
for (EntityColumn entityColumn : columns) {
boolean isPrimaryKey = entityColumn.isId();
//7.判断当前字段是否为主键
if (isPrimaryKey) {
//8.缓存主键的字段名和字段值
idColumn = entityColumn.getColumn();
//※返回格式如:#{record.age,jdbcType=NUMERIC,typeHandler=MyTypeHandler}
idHolder = entityColumn.getColumnHolder("record");
} else {
//9.使用非主键字段拼接SET子句
String column = entityColumn.getColumn();
String columnHolder = entityColumn.getColumnHolder("record");
builder.append(column).append("=").append(columnHolder).append(",");
}
}
builder.append("</set>");
//10.使用前面缓存的主键名、主键值拼接where子句
builder.append("where ").append(idColumn).append("=").append(idHolder);
builder.append("</foreach>");
//11.将拼接好的字符串返回
return builder.toString();
}
}
从获取表的各项属性后,完全就是一个拼SQL的过程,这个过程需要注意的是,这里拼的是XML中的形式。
3、继承扩展的 Mapper 接口
public interface MyMapper<T> extends
SelectAllMapper<T>,
SelectByPrimaryKeyMapper<T>,
MyBatchUpdateMapper<T> {
}
4、测试
public class ExtendsMapper {
private ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
private EmployeeService employeeService = ioc.getBean(EmployeeService.class);
@Test
public void test() {
List<Employee> empList = new ArrayList<Employee>(){{
add(new Employee(6, "Tom1", 1000.00, 20));
add(new Employee(7, "Tom2", 2000.00, 21));
add(new Employee(7, "Tom3", 3000.00, 22));
}};
employeeService.batchUpdateEmp(empList);
ioc.close();
}
}
public void batchUpdateEmp(List<Employee> empList) {
employeeMapper.batchUpdate(empList);
}
SQL语句:
UPDATE tabple_emp SET emp_name=?,emp_salary=?,emp_age=? where emp_id=? ;
UPDATE tabple_emp SET emp_name=?,emp_salary=?,emp_age=? where emp_id=? ;
UPDATE tabple_emp SET emp_name=?,emp_salary=?,emp_age=? where emp_id=?
注意:这种执行多条SQL语句的方式,需要进行设置,MySQL数据库默认不支持,开启允许批量执行
allowMultiQueries=true
jdbc.url=jdbc:mysql://localhost:3306/common_mapper?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· 面试官:你是如何进行SQL调优的?