12第九章:01_通用Mapper接口扩展

一、通用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") 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 final ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
    private final 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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值