@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;
    }

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

原文地址:https://www.cnblogs.com/zhyStudy/p/10532826.html