2014-07-23 27 views
2

所以我一直在抨擊我的頭,試圖加速從我的數據庫刪除過程。我對hibernate相對比較陌生,想知道是否可以在一個事務中執行多個操作。你可以使用休眠在一個事務中進行批量刪除嗎?

我不擔心事務無法刪除,所以回滾所有刪除的想法並不會打擾我。如果有助於提供表格說明,我也可以做到這一點。這個想法是,我必須刪除每個for循環內的內容,然後刪除它之外的內容。

我的代碼

private void deleteTrackItems() { 
     Session session = m_databaseConnection.getSession(); 
     Transaction tx = null; 
     try { 

      final List<TrackItem> trackItems = loadAllTrackItemByTrackID(
        track.getId(), session); 

      // Deletes all Track Items for the given track 
      List<Long> trackItemIds = new ArrayList(); 

      for (TrackItem trackItem : trackItems) { 
       trackItemIds.add(trackItem.getId()); 

       // this is test code 189 through 214 
       Set<TrackPoint> trackPoints = trackItem.getTrackPoints(); 

       for (TrackPoint trackPoint : trackPoints) { 

        // load track 
        final List<TrackPointDetail> trackPointDetails = loadAllTrackPointDetailByTrackID(
          trackPoint.getId(), session); 

        for (TrackPointDetail trackPointDetail : trackPointDetails) { 
         // delete track point details 
         deleteObject(trackPointDetail, session); 
        } 

        // delete track point 
        deleteObject(trackPoint, session); 
       } 

       // get the track informations 
       final Set<TrackInformation> trackInformations = trackItem 
         .getTrackInformations(); 

       // for each track information 
       for (TrackInformation trackInformation : trackInformations) { 
        deleteTrackInformation(trackInformation, session); 
       } 
       deleteObject(trackItem, session); 
      } 
     } 
     catch (Exception ex) { 
      System.out.println(ex); 
      tx.rollback(); 
     } 
     finally { 
      if (session != null) { 
       session.close(); 
      } 
     } 
    } 

/** 
* @param p_objectToDelete The object to delete 
* @param p_session the hibernate session 
* @return Returns the {@link Runnable} 
*/ 
protected void deleteObject(Object p_objectToDelete, final Session p_session) { 

    // get the transaction 
    final Transaction transaction = p_session.getTransaction(); 
    try { 
     LOGGER.info("Deleting object: " + p_objectToDelete.getClass()); 
     transaction.begin(); 
     p_session.delete(p_objectToDelete); 
     transaction.commit(); 
     LOGGER.info("Deleted object: " + p_objectToDelete.getClass()); 
    } 
    catch (Exception exception) { 
     transaction.rollback(); 
     LOGGER.error(exception); 
    } 
} 

因爲這些操作中的每一個執行後,每個刪除當前我在想,如果有可能做到這一點更多的批量操作的承諾。

我在想做的事情是沿着我的deleteObject函數拉出我的提交,並將其放在每個對象上調用delete的for循環的末尾。

所以

final Transaction tx = session.getTransaction(); 
transaction.begin(); 
try{ 
    for(Object object : objects){ 
     session.delete(object); 
    } 
    tx.commit(); 
}catch(Exception ex){ 
    System.out.println(ex); 
    tx.rollback(); 
} 

我其他的解決辦法,以批量刪除是使用Hibernate的SQLQuery在那裏我剛剛得到的ID每個的對象並將其存儲在一個列表中,並做了批量刪除在一個查詢的方式。不過,我覺得當我這樣做時,由於順序掃描,我的(?,?,?,?,?)列表中的哪個id需要更多時間。

我覺得應該有一個簡單的方法來使用hibernates session.delete()進行批量刪除。任何想法,不勝感激。

+1

你有沒有時間的方法?我非常懷疑查詢方法可能比上面的N + 1查詢策略需要更長的時間。 – kostja

回答

4

執行批量的常用方法刪除與Hibernate和JPA是完全一樣的,你在你的最後提出的解決方案 - 一個批量刪除查詢的HQL/JPQL

DELETE FROM MyEntity e WHERE e.id IN (:ids)

這應該是目前爲止最有效的一個作爲Hibernate不需要加載和實例化實體。

考慮將批量刪除放入其自己的事務性方法中,並儘快在其他方法中調用該方法 - 持久性上下文不會隨查詢結果更新,因此您希望阻止持久性上下文包含陳舊的數據。