MyBatis Batch Insert/Update For Oracle

2022-09-02 02:25:21

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

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

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

该功能已实现。但是我的技术主管说它的效率非常低,因为使用Java进行for循环并逐个插入/更新会消耗大量的系统资源。他建议我通过传递对象列表来使用myBatis进行批量插入。

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

我在myBatis中搜索合并的示例仅适用于一个对象,而不是批处理。因此,我想知道专家是否可以为我提供一些如何在MyBatis中进行批量合并的示例(编写Mapper的正确方法)?


答案 1

接受的答案不是处理批处理操作的推荐方法。它不显示真正的批处理语句,因为在打开会话时应使用批处理执行程序模式。请参阅此文章,其中代码贡献者建议批量更新(或插入)的正确方法是在批处理模式下打开会话,并重复调用更新(或插入)单个记录。

以下是对我有用的方法:

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,并确保它仅更新/插入单个记录。我遇到了无法解决的预言机错误,根据接受的答案(无效字符,语句未结束等)执行此操作。正如链接的帖子所示,接受的答案中显示的更新(或插入)实际上只是一个巨大的sql语句。


答案 2

在我的情况下,也有同样的情况。我使用for loop来检查此记录是否存在于databse中,然后根据这一点,我将此对象添加到两个数组列表中以进行插入或更新。然后使用批处理进行插入,并在for循环之后进行更新,以便列出。

这里是例如根据不同位置条件进行更新

1] 这是为了更新

<foreach collection="attendingUsrList" item="model"  separator=";">
    UPDATE parties SET attending_user_count = #{model.attending_count}
    WHERE  fb_party_id = #{model.eid}  
</foreach>

2] 这是用于插入

<insert id="insertAccountabilityUsers" parameterType="AccountabilityUsersModel" useGeneratedKeys="false">
    INSERT INTO accountability_users 
        (
            accountability_user_id, accountability_id, to_username,
            record_status, created_by, created_at, updated_by, updated_at
        ) 
    VALUES
    <foreach collection="usersList" item="model" separator=","> 
        (           
            #{model.accountabilityUserId}, #{model.accountabilityId}, #{model.toUsername}, 
            'A', #{model.createdBy}, #{model.createdAt}, #{model.updatedBy}, #{model.updatedAt}     
        )
    </foreach>
</insert>

在道法中声明为

void insertAccountabilityUsers(@Param("usersList") List<AccountabilityUsersModel> usersList);

更新

这是我的批处理会话代码

public static synchronized SqlSession getSqlBatchSession() {
    ConnectionBuilderAction connection = new ConnectionBuilderAction();
    sf = connection.getConnection();
    SqlSession session = sf.openSession(ExecutorType.BATCH);
    return session;
}

SqlSession session = ConnectionBuilderAction.getSqlSession(); 

实际上,我已经在这里给出了这个问题的完整示例


推荐