简体   繁体   English

MyBatis 批量插入/更新 Oracle

[英]MyBatis Batch Insert/Update For Oracle

I've recently started learning to use myBatis.I am now facing such a scenario, I need to constantly fetch a new list of Objects through WebService, then for this list, I need to insert/update each object into the oracle DB table through myBatis.最近开始学习使用myBatis,现在面临这样的场景,需要不断的通过WebService获取一个新的Object列表,然后对于这个列表,我需要通过插入/更新每个对象到oracle DB表我的Batis。

The tricky part is, I cannot simply do a batch insert every time, because some of the objects might already exist in DB, for these records, I need to update the fields of them instead of a new insertion.棘手的部分是,我不能每次都简单地进行批量插入,因为某些对象可能已经存在于 DB 中,对于这些记录,我需要更新它们的字段而不是新的插入。

My current solution might be very stupid, using Java, build the list of Object from webservice, loop through each of them, do a myBatis select, if it is not a null(already exists in the db), then do a myBatis update;我目前的解决方案可能很愚蠢,使用Java,从webservice 构建Object 列表,循环遍历每个对象,做一个myBatis select,如果它不是null(已经存在于db 中),然后做一个myBatis 更新; otherwise, do a myBatis insert for this new object.否则,为这个新对象做一个 myBatis 插入。

The function is achieved.功能实现了。 But my technical lead says it is very low-efficient, since doing a for loop using Java and insert/update one by one will consume a lot of system resource.但是我的技术负责人说它非常低效率,因为使用Java进行for循环并逐个插入/更新会消耗大量系统资源。 He advised me to do batch insert using myBatis by passing a list of objects in.他建议我通过传入对象列表来使用 myBatis 进行批量插入。

Batch insertion in myBatis is straightforward, however, since I am not purely inserting(for existing records I need to do update), I don't think batch insert is appropriate here. myBatis 中的批量插入很简单,但是,由于我不是纯粹的插入(对于我需要更新的现有记录),我认为这里不适合批量插入。 I've googled a while for this, and realized maybe I will need to use "merge" instead of "insert" (for Oracle).我为此搜索了一段时间,并意识到我可能需要使用“合并”而不是“插入”(对于 Oracle)。

The examples I googled out for merge in myBatis is only for one object, not in a batch.我在 myBatis 中搜索合并的示例仅适用于一个对象,而不是批处理。 Thus I want to find out whether experts could offer me some examples on how to do a batch-merge in MyBatis( The correct way to write a Mapper)?因此我想知道专家是否可以提供一些关于如何在 MyBatis 中进行批量合并的示例(编写 Mapper 的正确方法)?

The accepted answer is not the recommended way of handling batch operations.接受的答案不是处理批处理操作的推荐方式。 It does not show true batch statements since the batch executor mode should be used when opening a session.它不显示真正的批处理语句,因为在打开会话时应使用批处理执行程序模式。 See this post in which a code contributor recommended that the proper way to batch update (or insert) is to open a session in batch mode and repeatedly call update (or insert) for a single record.请参阅此帖子,其中代码贡献者建议批量更新(或插入)的正确方法是以批处理模式打开会话并重复调用单个记录的更新(或插入)。

Here's what works for me:以下是对我有用的内容:

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

Do not use foreach in your update/insert and ensure that it only updates/inserts a single record.不要在更新/插入中使用 foreach 并确保它只更新/插入一条记录。 I was running into unsolvable oracle errors by doing it according to the accepted answer (invalid character, statement not ended, etc.).根据接受的答案(无效字符、语句未结束等)执行此操作,我遇到了无法解决的 oracle 错误。 As the linked post indicates, the update (or insert) shown in the accepted answer is actually just a giant sql statement.正如链接的帖子所示,已接受的答案中显示的更新(或插入)实际上只是一个巨大的 sql 语句。

In my case also there is same scenario.就我而言,也有相同的情况。 I used for loop to check whether this record exists in databse or not and then according to that I added this object in to two arraylist for insert or update.我使用 for 循环来检查此记录是否存在于数据库中,然后根据我将此对象添加到两个数组列表中以进行插入或更新。 And then used batch for insert and update after for loop for that to list.然后在 for 循环后使用批处理进行插入和更新,以便列出。

here is ex.这是前。 for update according to different where condition根据不同的where条件进行更新

1] this is for update 1]这是为了更新

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

2] this is for insert 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>

In dao method declare as在 dao 方法中声明为

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

Update更新

Here is my batch session code这是我的批处理会话代码

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

SqlSession session = ConnectionBuilderAction.getSqlSession(); 

Actually I already given full example here for this question 其实我已经在这里给出了这个问题的完整例子

In oracle if you want to execute multiple statements at one time you have to enclose your statements in "begin" and "end" block.在 oracle 中,如果您想一次执行多个语句,则必须将语句括在“begin”和“end”块中。 So try to add attributes to foreach as below.因此,尝试为 foreach 添加属性,如下所示。 This will definitely work.这肯定会奏效。


<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