2012-10-15 140 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