繁体   English   中英

MyBatis 批量插入/更新 Oracle

[英]MyBatis Batch Insert/Update For Oracle

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

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

我目前的解决方案可能很愚蠢,使用Java,从webservice 构建Object 列表,循环遍历每个对象,做一个myBatis select,如果它不是null(已经存在于db 中),然后做一个myBatis 更新; 否则,为这个新对象做一个 myBatis 插入。

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

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

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

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

以下是对我有用的内容:

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

就我而言,也有相同的情况。 我使用 for 循环来检查此记录是否存在于数据库中,然后根据我将此对象添加到两个数组列表中以进行插入或更新。 然后在 for 循环后使用批处理进行插入和更新,以便列出。

这是前。 根据不同的where条件进行更新

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>

在 dao 方法中声明为

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(); 

其实我已经在这里给出了这个问题的完整例子

在 oracle 中,如果您想一次执行多个语句,则必须将语句括在“begin”和“end”块中。 因此,尝试为 foreach 添加属性,如下所示。 这肯定会奏效。


<foreach collection="customerList" item="object" open="begin" close=";end;" separator=";">
    UPDATE customer SET isActive = #{object.isactive}
    WHERE  customerId= #{object.customerId}
</foreach>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM