【问题标题】:Using HashMap dynamically for parameter mapping in mybatismybatis中动态使用HashMap进行参数映射
【发布时间】:2021-09-13 17:52:33
【问题描述】:

好的,这有点像重新发布这个问题Inserting HashMap Values to a table using ibatis(但我正在寻找一种不同的方式——答案对我不起作用)..

DB1GetStudentDataMapper.xml(此查询到一个数据库)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.testing.db1.DB1GetStudentDataMapper">

<select id="selectAllStudents" resultType="java.util.Map">
        SELECT STUDENT_CD, STUDENT_NM, PARENT_CD, CREATED_DATE
        FROM STUDENT
        WHERE STD_STATUS='ACT'
</select>

</mapper>

DB2InsertStudentMapper.xml(此查询到不同的数据库)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.testing.db2.DB2InsertStudentMapper">
                
<insert id="insertStudent" parameterType="java.util.HashMap">
  INSERT INTO STUDENT
  <!-- dynamically select column names from hashmap -->
  (#{stdMap.keySet}) // this is not working - its coming as null
   <!-- dynamically select values for the above columns from hashmap -->
   VALUES (#{stdMap.values}) // this is not working - its coming as null
</insert>
           
</mapper>

DB2InsertStudentMapper.java

public interface TMODSBDataRefreshMapper {
    
    void insertStudent(@Param("stdMap") HashMap stdMap);
}

StudentDataProcess.java

public class Student {
    
    // I have defaultExecutorType as BATCH in my mapper config file
    
        private DB1GetStudentDataMapper db1Mapper; // Interface Mapper for first data source
        private DB2InsertStudentMapper db2Mapper; // Interface Mapper for second data source
        
        public processStudent() throws Exception {
            
            List<HashMap> rs = db1Mapper.selectAllStudents(); // Gets some 15k+ records
            for(int i =0; i < rs.size(); i++) { // so this will loop through 15k+ records
                HashMap result = rs.get(i);
                System.out.println(result.keySet()); // prints column names from select query [STUDENT_CD, STUDENT_NM, PARENT_CD, CREATED_DATE]
                System.out.println(result.values()); // prints above column values of first data set [1001, Mike, 5001, 2021-07-01]
                
                // All I am trying is to insert above 15k records into different database dynamically rather than creating POJO
                db2Mapper.insertStudent(result);
            }
            
        }
            
}

注意:例如,我使用了 4 列 - 我有大约 150 多列可以使用..

PS:请记住,当您使用较少的列时,此解决方案效果更好 - 但如果您有批量插入则效果不佳 - 它会影响性能。

【问题讨论】:

标签: java hashmap mybatis


【解决方案1】:

使用&lt;foreach /&gt; 迭代映射时,键和值分别分配给indexitem 中指定的变量。
因此,您的插入语句应该如下所示。

<insert id="insertStudent">
  INSERT INTO STUDENT (
    <foreach collection="stdMap" index="col" separator=",">
      ${col}
    </foreach>
  ) VALUES (
    <foreach collection="stdMap" item="val" separator=",">
      #{val}
    </foreach>
  )
</insert>
  • 您必须使用${} 作为列名,使用#{} 作为值。详情请参阅FAQ
  • 要以相同的顺序迭代地图,您应该使用java.util.LinkedHashMap 作为&lt;select /&gt; 的结果类型。

【讨论】:

  • 太棒了 - 这按预期工作.. 非常感谢!但是如果我们在性能方面使用 foreach 会有什么问题吗?当我要插入大约 150 多列时?
  • ? 肯定会有一些不同,但如果你一次只插入一行,我不会太担心。另一方面,如果您计划使用此语句插入大量行并且性能很重要,那么这可能不是最好的方法。
  • 是的,我们实际上是在做一个 BATCH 插入.. 这个语句需要更长的时间.. 有什么更好的替代方法可以通过 mybatis 更快地插入记录??
  • 对于这样的任务(即将数据从一个数据库迁移到另一个数据库),使用 MyBatis(或任何持久化工具)几乎没有优势。像COPY 这样的本机命令可能是最快的选择。如果必须通过 JDBC 完成,我会直接使用 JDBC 及其批处理 API(即addBatch()executeBatch())。您可能可以通过使用ResultSetMetaData 使其具有一定的动态性。
  • 是的有道理.. ya 这两个数据库都有不同的表或模型.. 所以 COPY 命令可能不是我们的选择..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-21
  • 2018-12-25
  • 2014-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多