Java 针对Oracle的MyBatis批量插入/更新
我最近开始学习使用myBatis。我现在面临这样一种情况,我需要通过WebService不断获取一个新的对象列表,然后对于这个列表,我需要通过myBatis将每个对象插入/更新到oracle DB表中 棘手的是,我不能每次都简单地进行批量插入,因为有些对象可能已经存在于数据库中,对于这些记录,我需要更新它们的字段,而不是新的插入 我当前的解决方案可能非常愚蠢,使用Java,从webservice构建对象列表,循环遍历每个对象,执行myBatis选择,如果它不是null(已经存在于数据库中),则执行myBatis更新;否则,请为此新对象执行myBatis插入 实现了该功能。但是我的技术负责人说它效率很低,因为使用Java和逐个插入/更新进行for循环将消耗大量的系统资源。他建议我使用myBatis进行批插入,方法是将对象列表传入 myBatis中的批插入很简单,但是,因为我不是纯粹的插入(对于需要更新的现有记录),所以我认为批插入在这里不合适。我在谷歌上搜索了一段时间,意识到也许我需要使用“合并”而不是“插入”(对于Oracle)Java 针对Oracle的MyBatis批量插入/更新,java,sql,oracle,mybatis,Java,Sql,Oracle,Mybatis,我最近开始学习使用myBatis。我现在面临这样一种情况,我需要通过WebService不断获取一个新的对象列表,然后对于这个列表,我需要通过myBatis将每个对象插入/更新到oracle DB表中 棘手的是,我不能每次都简单地进行批量插入,因为有些对象可能已经存在于数据库中,对于这些记录,我需要更新它们的字段,而不是新的插入 我当前的解决方案可能非常愚蠢,使用Java,从webservice构建对象列表,循环遍历每个对象,执行myBatis选择,如果它不是null(已经存在于数据库中),则执
我在myBatis中搜索到的用于合并的示例仅适用于一个对象,而不是批处理。因此,我想知道专家们是否可以为我提供一些关于如何在MyBatis(编写映射程序的正确方法)中进行批量合并的示例。在我的例子中,也有相同的场景。我使用for循环检查数据库中是否存在该记录,然后根据检查结果将该对象添加到两个arraylist中以进行插入或更新。 然后使用批处理进行插入,并在循环之后进行更新,以便列出 这里是根据不同的位置条件进行更新的示例 1] 这是更新
<foreach collection="attendingUsrList" item="model" separator=";">
UPDATE parties SET attending_user_count = #{model.attending_count}
WHERE fb_party_id = #{model.eid}
</foreach>
公认的答案不是处理批处理操作的推荐方法。它不显示真正的批处理语句,因为在打开会话时应使用批处理执行器模式。在本文中,代码贡献者建议批量更新(或插入)的正确方法是以批处理模式打开会话,并重复调用单个记录的更新(或插入) 以下是对我有效的方法:
public void updateRecords(final List<GisObject> objectsToUpdate) {
final SqlSession sqlSession = MyBatisUtils.getSqlSessionFactory().openSession(ExecutorType.BATCH);
try {
final GisObjectMapper mapper = sqlSession.getMapper(GisObjectMapper.class);
for (final GisObject gisObject : objectsToUpdate) {
mapper.updateRecord(gisObject);
}
sqlSession.commit();
} finally {
sqlSession.close();
}
}
公共作废更新记录(最终列表对象更新){
final SqlSession SqlSession=MyBatisUtils.getSqlSessionFactory().openSession(ExecutorType.BATCH);
试一试{
最终的GisObjectMapper映射器=sqlSession.getMapper(GisObjectMapper.class);
用于(最终的GisObject GisObject:objectsToUpdate){
mapper.updateRecord(gisObject);
}
提交();
}最后{
sqlSession.close();
}
}
请勿在更新/插入中使用foreach,并确保它仅更新/插入单个记录。根据公认的答案(无效字符、语句未结束等),我遇到了无法解决的oracle错误。正如链接的帖子所指出的,接受答案中显示的更新(或插入)实际上只是一个巨大的sql语句。在oracle中,如果要同时执行多个语句,必须将语句括在“开始”和“结束”块中。因此,尝试向foreach添加属性,如下所示。这肯定会奏效的
<foreach collection="customerList" item="object" open="begin" close=";end;" separator=";">
UPDATE customer SET isActive = #{object.isactive}
WHERE customerId= #{object.customerId}
</foreach>
更新客户集isActive=#{object.isActive}
其中customerId=#{object.customerId}
是,但如果列表大小为零,则不要调用insert或update方法,否则将引发语法错误。不起作用…给出错误的SQL语法[];嵌套异常为java.sql.BatchUpdateException:ORA-00933命令终止错误提供的插入解决方案不适用于Oracle DB。这不是批插入/更新,而是一个巨大的sql语句。请看这里,Oracle不能用这种方式进行更新和插入。这很酷。当与spring一起使用时,可以通过sqlSessionFactory.openSession(ExecutorType.BATCH,false)
(使用批处理模式)获得这样的sql会话,并禁用自动提交。谢谢@Eric Wang,我不确定当时是谁做的,希望有人会插嘴。声誉历史似乎没有显示姓名。然而,似乎Sameer Kazi这样做是因为在他编辑自己的帖子一分钟后出现了否决票。嘿,这不是批量更新,你在for循环中调用update方法意味着数据库在for循环中调用,所以这不是批量更新,在选定的回答中,只有一个数据库调用和更新。
public static synchronized SqlSession getSqlBatchSession() {
ConnectionBuilderAction connection = new ConnectionBuilderAction();
sf = connection.getConnection();
SqlSession session = sf.openSession(ExecutorType.BATCH);
return session;
}
SqlSession session = ConnectionBuilderAction.getSqlSession();
public void updateRecords(final List<GisObject> objectsToUpdate) {
final SqlSession sqlSession = MyBatisUtils.getSqlSessionFactory().openSession(ExecutorType.BATCH);
try {
final GisObjectMapper mapper = sqlSession.getMapper(GisObjectMapper.class);
for (final GisObject gisObject : objectsToUpdate) {
mapper.updateRecord(gisObject);
}
sqlSession.commit();
} finally {
sqlSession.close();
}
}
<foreach collection="customerList" item="object" open="begin" close=";end;" separator=";">
UPDATE customer SET isActive = #{object.isactive}
WHERE customerId= #{object.customerId}
</foreach>