2012-10-15 80 views
4

是否可以在標記爲Spring的方法中執行提交@Transactional在@Transactional事務中提交

@PersistenceContext 
private EntityManager em; 

@Transactional(propagation = Propagation.REQUIRED) 
public void saveMembersWithMultipleCommits(List<Member> members) 
    throws HibernateException 
{ 
    Iterator<Member> it = members.iterator(); 
    while (it.hasNext()) 
    { 
     while (it.hasNext()) 
     { 
      Member wsBean = it.next(); 
      em.persist(wsBean); // overall commit will be made after method exit 
      log.info("Webservices record " + wsBean + " saved. " + i++); 
     } 
    } 
} 

我想說每500個項目後提交數據庫。上述情況可能嗎?

回答

5

不,你需要做的編程方式使用,例如,TransactionTemplate API。閱讀更多here

它看起來像

while (it.hasNext()) 
{ 
    transactionTemplate.execute(new TransactionCallbackWithoutResult() { 
     protected void doInTransactionWithoutResult(TransactionStatus status) { 
      int counter = 0; 
      while (it.hasNext() && counter++ < 500) { 
       Member wsBean = it.next(); 
       em.persist(wsBean); 
       log.info("Webservices record " + wsBean + " saved. " + i++); 
      } 
     } 
    ); 
} 
+0

因此,我將有一個新的連接到DB每個回調? –

+0

@MichaelZ不,只是一個新的交易。 – pap

5

您的問題表明您錯位了您的交易邊界。

您可以將持久調用移入私有方法,並使該方法爲事務性而不是外部方法。這種方法一次可以接受500個成員,然後在退出時提交。

+7

需要加載時或編譯時編織,不會與泉工作「標準「基於代理的編織。 – pap

+0

是的,這是真的。 –

1

如果你期待着您的其他事務內部事務提交,您可能需要使用@Transactional (propagation = Propagation.REQUIRES_NEW)

+0

我是否會爲第二個@Transactional方法調用打開DB的新連接,或者它會是相同的連接? –

+0

這是一個完全分開的「事務」,但連接是相同的。自己檢查一下。我可能會犯一個錯誤。 –

0

替代戰略是創建在DAO的方法並將其標記爲@Transactional。此方法將進行批量更新(例如500個)。所以,你可以有代碼的方法

@Transactional 

public void mybatchUpdateMethod(){ 

    StatelessSession session = this.hibernateTemplate.getSessionFactory() 
      .openStatelessSession(); 

    Transaction transaction = null; 

    Long entryCounter = 0L; 

    PreparedStatement batchUpdate = null; 
    try { 
     transaction = session.beginTransaction(); 
     batchUpdate = session.connection().prepareStatement(insertSql); 

     for (BatchSnapshotEntry entry : entries) { 
      entry.addEntry(batchUpdate); 
      batchUpdate.addBatch(); 

      if (++entryCounter == 500) { 
       // Reached limit for uncommitted entries, so commit 
       batchUpdate.executeBatch(); 
      } 
     } 

     batchUpdate.executeBatch(); 
     batchUpdate.close(); 
     batchUpdate = null; 
    } 
    catch (HibernateException ex) { 
     transaction.rollback(); 
     transaction = null; 
    } 
} 

每次調用這個方法時,它會經過500個的插入/更新提交

+0

這裏是什麼_hibernateTemplate_?什麼級別? –

+0

對不起。應該澄清。我使用hibernate和hibernateTemplate給出了spring的例子。您正在使用與JPA一起使用的EntityManager並可以使用它。你可以這樣做Session session = entityManager.unwrap(Session.class);會話是休眠會話 – vsingh