以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; }
到此就完成了自动化方法,这个只是粗劣的写一下,希望各位看过的大佬,指出不足