MyBatis version2.0.4

Database vendor and version

mysql

Test case or example project

1.mapper public interface SaveDataMapper {

@InsertProvider(
        type = SaveDataListProvider.class,
        method = "insertList"
)
<T> int insertList(@Param("class") T clazz, @Param("list") List<T>  var1);

} 2. provider method public String insertList(Map params) {

    Class entityClass = (Class) params.get("class");
    List datas = (List) params.get("list");

    String clazzName = entityClass.getName();
    String tableName = clazzName.substring(clazzName.lastIndexOf(".") + 1, clazzName.length());
    StringBuilder sql = new StringBuilder();
    sql.append("insert into " + tableName + " ");
    sql.append(getColumns(entityClass, true, false, false));
    sql.append("  VALUES  ");
   // sql.append(" (");
     sql.append("<foreach collection=\"list\" item=\"record\" separator=\",\" >");
     sql.append("<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">");
    Set<String> columnList = getColumnsByEntityClass(entityClass);
    Iterator var5 = columnList.iterator();

    while (var5.hasNext()) {
        String column = (String) var5.next();
        if (!column.equals("id")) {
            sql.append(getColumnHolder("record", column) + ",");
        }
    }
    //sql.substring(0, sql.length() - 2);
    //sql.append(" )");
    sql.append("</trim>");
    sql.append("</foreach>");
    logger.info("final insert sql: " + sql);
    return sql.toString();
}

Steps to reproduce

just call this method

Expected result

my provider can insert normally like SpecialProvider

Actual result

my provider call ProviderSqlSource to parse sql, can not Resolve foreach tags ,just replace #{} in my sql statement

Comment From: h3adache

Are you reporting an issue regarding sql provider? Batch inserts is not the same as using the foreach tag. For a really good explanation and example of batch inserts look at @harawata’s blog post here https://blog.harawata.net/2016/04/bulk-insert-multi-row-vs-batch-using.html

Comment From: shangmingzhen

@h3adache hi,thank u for you replay. i read the blog you mention to . Well, i facing a more complex situation, my class of entity generate at runtime, so, i can not use normal xml or mapper interface . i wanna use provider to muti-row insert, because i can pass the entity class as one of params. however, my provider pasting in code front ,but ,when calling provider using providerSqlSource not DynamicSqlSource,it just replace placeHolder #{} not parse forEach tags. So, i am wandering wether self-define provider can implement muti-row insert function with forEach tag. BWT

Comment From: harawata

@shangmingzhen , Add @Lang(XMLLanguageDriver.class) to the mapper method (requires MyBatis 3.5.1 or newer). There is a test case.

@h3adache , I need to rewrite the benchmark part of that post using JMH. :D

Comment From: shangmingzhen

@harawata hi, i add the annotaiton @Lang(XMLLanguageDriver.class) to my mapper, public interface SaveDataMapper { @Lang(XMLLanguageDriver.class) @InsertProvider( type = SaveDataListProvider.class, method = "insertList" ) int insertList(@Param("class") T clazz, @Param("list") List var1);

}

well, this time just call method ' getBoundSql(Object parameterObject)' of RawSqlSource, still does not parse forEach tags in my provider. what i can do next?

Comment From: harawata

@shangmingzhen , Weird. Please provide a repro. A test case or an example project like these. And make sure to use MyBatis 3.5.1 or later. You wrote that you are using version 2.0.4 which does not exist.

Comment From: shangmingzhen

@harawata i use version 3.5.1 now , my method in provider is following: public String insertList(Map params) {

    Class entityClass = (Class) params.get("class");
    List datas = (List) params.get("list");

    String clazzName = entityClass.getName();
    String tableName = clazzName.substring(clazzName.lastIndexOf(".") + 1, clazzName.length());
    StringBuilder sql = new StringBuilder();
    sql.append("insert into " + tableName + " ");
    sql.append(getColumns(entityClass, true, false, false));
    sql.append("  VALUES  ");
   // sql.append(" (");
     sql.append("<foreach collection=\"list\" item=\"record\" separator=\",\" >");
     sql.append("<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">");
    Set<String> columnList = getColumnsByEntityClass(entityClass);
    Iterator var5 = columnList.iterator();

    while (var5.hasNext()) {
        String column = (String) var5.next();
        if (!column.equals("id")) {
            sql.append(getColumnHolder("record", column) + ",");
        }
    }
    //sql.substring(0, sql.length() - 2);
    //sql.append(" )");
    sql.append("</trim>");
    sql.append("</foreach>");
    logger.info("final insert sql: " + sql);
    return sql.toString();
}

is it wrong?

Comment From: harawata

@shangmingzhen , Please provide us with something executable (test case or example project). I already showed you the working test case, so there is no point in me creating another test.

Comment From: shangmingzhen

@harawata thank u for you repaly, i think i get the problem. i debug into mybatis source code ,the annotaion @lang(XMLLanguageDriver.class) work indeed. While, if i wanna to call dynamicSqlSource, i must to include my sql statement while '