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

到此就完成了自動化方法,這個只是粗劣的寫一下,希望各位看過的大佬,指出不足


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM