Mapper系列四:Mapper接口扩展

扩展是指增加通用 Mapper 没有提供的功能。
举例:
通用 Mapper 官方文档中使用一个批量 insert 作为扩展功能的例子:  tk.mybatis.mapper.additional.insert.InsertListMapper<T>tk.mybatis.mapper.additional.insert.InsertListProvider
我们来仿照写一个批量 update。假设我们想生成下面这样的 SQL 语句:

UPDATE tabple_emp SET emp_name=?,emp_age=?,emp_salary=? where emp_id=?;
UPDATE tabple_emp SET emp_name=?,emp_age=?,emp_salary=? where emp_id=?; 
UPDATE tabple_emp SET emp_name=?,emp_age=?,emp_salary=? where emp_id=?; 

为了生成上面那样的 SQL 语句,我们需要使用到 MyBatis 的 foreach 标签。

<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>

1、创建扩展接口MyBatchUpdateMapper

public interface MyBatchUpdateMapper<T> {
	
	@UpdateProvider(type=MyBatchUpdateProvider.class, method="dynamicSQL")
	void batchUpdate(List<T> list);
}

2、创建MyBatchUpdateProvider拼装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 statement) {
		//1.创建StringBuilder用于拼接SQL语句的各个组成部分
		StringBuilder builder = new StringBuilder();
		//2.拼接foreach标签
		builder.append("<foreach collection=\"list\" item=\"record\" separator=\";\" >");
		//3.获取实体类对应的Class对象
		Class<?> entityClass = super.getEntityClass(statement);
		//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();
	}
}

3、MyMapper继承扩展接口MyBatchUpdateMapper

public interface MyMapper<T> 
		extends SelectAllMapper<T>,SelectByExampleMapper<T>,MyBatchUpdateMapper<T> {
}

测试:
注意:JDBC要执行分号隔开的SQL语句。必须在连接数据库时添加参数allowMultiQueries=true
在这里插入图片描述

public class MyBatchUpdateTest {
	
	public static void main(String[] args) {
		ClassPathXmlApplicationContext iocContainer = new ClassPathXmlApplicationContext("spring-context.xml");
		EmployeeService employeeService = iocContainer.getBean(EmployeeService.class);
		
		List<Employee> empList = new ArrayList<Employee>();
		
		empList.add(new Employee(25, "newName01", 111.11, 10));
		empList.add(new Employee(26, "newName02", 222.22, 20));
		empList.add(new Employee(27, "newName03", 333.33, 30));
		
		employeeService.batchUpdateEmp(empList);
		iocContainer.close();
	}
}

控制台输出:

Preparing: 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=?   
Parameters: newName01(String), 111.11(Double), 10(Integer), 1(Integer), newName02(String), 222.22(Double), 20(Integer), 2(Integer), newName03(String), 333.33(Double), 30(Integer), 3(Integer)  
Updates: 1  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值