zoukankan      html  css  js  c++  java
  • 通用Mapper(九)通用 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")
        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
    

      

     
  • 相关阅读:
    @try { } @catch (NSException *exception) {} @finally {}
    键盘点出来就退不掉了,你可以把这几句加到有键盘的控制器里
    测试最新的微信iOS SDK 报错误
    堆、栈知识小结
    PV操作
    continue & break
    dll的def文件与__declspec(dllexport)导出函数方式比较
    setupapi.h和setupapi.lib該如何使用
    批量缺少头文件的解决办法(添加包含目录)
    易犯错误总结:
  • 原文地址:https://www.cnblogs.com/niujifei/p/15291149.html
Copyright © 2011-2022 走看看