Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 针对Oracle的MyBatis批量插入/更新_Java_Sql_Oracle_Mybatis - Fatal编程技术网

Java 针对Oracle的MyBatis批量插入/更新

Java 针对Oracle的MyBatis批量插入/更新,java,sql,oracle,mybatis,Java,Sql,Oracle,Mybatis,我最近开始学习使用myBatis。我现在面临这样一种情况,我需要通过WebService不断获取一个新的对象列表,然后对于这个列表,我需要通过myBatis将每个对象插入/更新到oracle DB表中 棘手的是,我不能每次都简单地进行批量插入,因为有些对象可能已经存在于数据库中,对于这些记录,我需要更新它们的字段,而不是新的插入 我当前的解决方案可能非常愚蠢,使用Java,从webservice构建对象列表,循环遍历每个对象,执行myBatis选择,如果它不是null(已经存在于数据库中),则执

我最近开始学习使用myBatis。我现在面临这样一种情况,我需要通过WebService不断获取一个新的对象列表,然后对于这个列表,我需要通过myBatis将每个对象插入/更新到oracle DB表中

棘手的是,我不能每次都简单地进行批量插入,因为有些对象可能已经存在于数据库中,对于这些记录,我需要更新它们的字段,而不是新的插入

我当前的解决方案可能非常愚蠢,使用Java,从webservice构建对象列表,循环遍历每个对象,执行myBatis选择,如果它不是null(已经存在于数据库中),则执行myBatis更新;否则,请为此新对象执行myBatis插入

实现了该功能。但是我的技术负责人说它效率很低,因为使用Java和逐个插入/更新进行for循环将消耗大量的系统资源。他建议我使用myBatis进行批插入,方法是将对象列表传入

myBatis中的批插入很简单,但是,因为我不是纯粹的插入(对于需要更新的现有记录),所以我认为批插入在这里不合适。我在谷歌上搜索了一段时间,意识到也许我需要使用“合并”而不是“插入”(对于Oracle)


我在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>