2014-05-06 119 views
15

我最近開始學習使用myBatis.I現在面臨這樣的情況,我需要不斷地通過WebService獲取一個新的對象列表,然後對於這個列表,我需要插入/通過myBatis將每個對象更新到oracle數據庫表中。MyBatis批量插入/更新Oracle

棘手的部分是,我不能簡單地每次都做一個批量插入,因爲一些對象可能已經存在於DB中,對於這些記錄,我需要更新它們的字段而不是新的插入。

我目前的解決方案可能是非常愚蠢的,使用Java,從webservice建立對象列表,循環遍歷每個對象,做一個myBatis選擇,如果它不是null(在db中已經存在),然後執行一個myBatis更新;否則,爲這個新對象做一個myBatis插入。

該功能已實現。但是我的技術負責人說這樣做效率很低,因爲使用Java進行for循環並逐個插入/更新會佔用大量的系統資源。他建議我使用myBatis進行批量插入,方法是傳入一個對象列表。

myBatis中的批量插入很簡單,但是,因爲我不是純粹插入(對於現有記錄,我需要更新),所以我不' t認爲批量插入在這裏是適當的。我爲此已經搜索了一段時間,並意識到可能我需要使用「合併」而不是「插入」(對於Oracle)。

我在myBatis中用於合併的示例僅適用於一個對象,而不是批處理。因此,我想知道專家是否可以提供一些有關如何在MyBatis中進行批量合併(寫入Mapper的正確方法)的示例?

回答

21

在我的情況下也有相同的情況。我用for循環來檢查這條記錄是否存在於數據庫中,然後根據該記錄將此對象添加到兩個數組列表中進行插入或更新。 然後使用批處理插入和更新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> 

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

Actually I already given full example here for this question

+0

@ Sammer Kazi,當然。但是你正在更新並分別插入自己的? – Kevin

+0

是for循環結束後,我運行了兩個批量更新和批量插入查詢。並在我的循環,我只檢查是否這個記錄退出分貝或不。在上面的例子中,插入和更新查詢僅僅是在這裏,它們對於循環來說不是相同的。 –

+0

哦,我有點了解。在java級別,您遍歷列表,然後創建兩個子列表,sublist1包含DB中的對象,sublist2包含不是的對象。那麼對於sublist1,你做了批量更新,對於sublist2你做批量插入? – Kevin

22

接受的答案是不處理批處理操作的推薦方式。它不顯示真正的批處理語句,因爲在打開會話時應使用批處理執行程序模式。請參閱post,其中代碼撰稿人建議批量更新(或插入)的正確方法是以批處理模式打開會話並重復調用更新(或插入)單個記錄。

這裏對我來說是什麼在起作用:

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語句。

+0

這很酷。當使用spring時,可以通過'sqlSessionFactory.openSession(ExecutorType.BATCH,false)'獲得這樣的sql會話,它使用批處理模式,並禁用自動提交。 –

+1

爲什麼downvote? – rimsky

+2

不是我,我upvoted, –