zoukankan      html  css  js  c++  java
  • @InsertProvider 根据bean属性,自动生成插入sql语句

    以Test为例,用mybatis的@InsertProvider的注解插入数据的时候,每次都要写类似于

    Mapper类

    @Mapper
    public interface TestDao {
        
        @InsertProvider(type = TestSqlProvider.class,method="insertAll")
        public void insertOrderLine(@Param("list")List<Test> list);
    
    }
    SqlProvider方法
        public String insertAll(Map map) {
            List<Test> list = (List<Test>) maop.get("list");
            StringBuilder sb = new StringBuilder();
            sb.append("INSERT INTO TEST");
            sb.append("(PKEY,NAME,AGE,SEX");
            sb.append("VALUES");
            MessageFormat mf = new MessageFormat(
                    "#'{'list[{0}].pkey},#'{'list[{0}].name},#'{'list[{0}].age},#'{''list[{0}].sex}");
            for (int i = 0; i < list.size(); i++) {
                sb.append(mf.format(new Object[] { i }));
                if (i < list.size() - 1)
                    sb.append(",");
            }
            return sb.toSting();
        }

    这种方式的话,写法很繁琐,如果字段多,就特别麻烦。所以我在想可不可以通过一种比较通用化的方式,生成插入语句。
    方式:
    用一个注解的形式,记录字段对应的数据库列名
    注解类:

    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Columns {
    
        String value();//字段名
        
        String comment() default "";//注释
        
        
    }

    在Test类的字段中加上@Columns注解

    例如:

        @Columns(value = "PKEY",comment = "主键")
        protected Integer pkey;//主键

    然后写一个工具类,通过反射生成插入语句

    方法:

    public static String getInsertSql(Class<?> clas,int size) {
            String tableName = SCHEMAS + "." + underscoreName(clas.getSimpleName());
            List<Field> fieldList = getSuperFields(clas);
            StringBuilder insertTable = new StringBuilder();
            insertTable.append("INSERT INTO ");
            insertTable.append(tableName);
            StringBuilder columnsStr = new  StringBuilder("(");
            StringBuilder valuesStr = new StringBuilder("(");
            for (int i = 0; i < fieldList.size(); i++) {
                fieldList.get(i).setAccessible(true);
                Columns columns = fieldList.get(i).getAnnotation(Columns.class);
                if (columns != null) {
                    columnsStr.append(columns.value());
                    
                }
                String fieldName = fieldList.get(i).getName();
                if (fieldName.equals("pkey")) {//db2自定生成自增主键的方式,也可以uuid
                    valuesStr.append("default");
                }else {
                    valuesStr.append("#'{'list[{0}].").append(fieldName).append("}");
                }
                if (i < fieldList.size() - 1) {
                    valuesStr.append(",");
                    columnsStr.append(",");
                }
            }
            columnsStr.append(")");
            valuesStr.append(")");
            
            StringBuilder sql = new StringBuilder();
            sql.append(insertTable).append(columnsStr).append("VALUES");
            MessageFormat mf = new MessageFormat(valuesStr.toString());
            for (int i = 0; i < size; i++) {
                sql.append(mf.format(new Object[] { i }));
                if (i < size - 1) {
                    sql.append(",");
                }
            }
            
            return sql.toString();
        }
        
        // 驼峰转大写+下划线,abcAbcaBc->ABC_ABCA_BC
        public static String underscoreName(String name) {
            StringBuilder result = new StringBuilder();
            if ((name != null) && (name.length() > 0)) {
                result.append(name.substring(0, 1).toUpperCase());
                for (int i = 1; i < name.length(); i++) {
                    String s = name.substring(i, i + 1);
                    if ((s.equals(s.toUpperCase())) && (!Character.isDigit(s.charAt(0)))) {
                        result.append("_");
                    }
                    result.append(s.toUpperCase());
                }
            }
            System.err.println("underscoreName:" + result.toString());
            return result.toString();
        }
    
        /**
         * 
         * <p>Title: getSuperFields</p>  
         * <p>Description:获取所有属性,包含父类</p>  
         * @param clas
         * @return
         */
        public static List<Field> getSuperFields(Class<? extends BeanBase> clas) {
            List<Field> fieldList = new ArrayList<>() ;
            while (clas != null) {//取父类属性
                  fieldList.addAll(Arrays.asList(clas .getDeclaredFields()));
                  clas = (Class<? extends BeanBase>) clas.getSuperclass(); //父类
            }
            return fieldList;
        }

    insetAll的写法

        public String insertAll(Map map) {
            List<Test> list = (List<Test>) map.get("list");
            String insertSql = BeanUtils.getInsertSql(Test.class, list.size());
            return insertSql;
        }

    到此就完成了自动化方法,这个只是粗劣的写一下,希望各位看过的大佬,指出不足

  • 相关阅读:
    面试题 31: 求子数组的最大和
    [面试] 结构体占用空间的问题,内存对齐~! 真的懂了,cpu取加快速度,省空间来考虑。
    [计算机] 32768~32767 计算机中的 1 表示
    C#跨线程调用窗体控件
    合并字节数组
    将汉字转化为2位大写的16进制Unicode
    关公与子龙两大杀手
    早年的J2EE笔记
    给小组新成员的一份信
    c++虚函数详解
  • 原文地址:https://www.cnblogs.com/zhyStudy/p/10532826.html
Copyright © 2011-2022 走看看