4

是否可以在标记为 Spring 的@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 个项目后提交给 DB。在上述背景下这可能吗?

4

4 回答 4

5

不,您需要使用例如TransactionTemplateAPI 以编程方式进行。在这里阅读更多。

它看起来像

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++);
            }
        }
    );
}
于 2012-10-15T14:50:40.907 回答
4

您的问题表明您放错了交易边界。

您可以将持久调用移动到私有方法中,并使该方法具有事务性,而不是外部方法。此方法一次可以接受 500 个成员,然后在退出时提交。

于 2012-10-15T14:43:38.937 回答
2

如果您期待在其他事务中以事务方式提交,则可能需要使用@Transactional (propagation = Propagation.REQUIRES_NEW)

于 2012-10-15T14:47:46.443 回答
-2

替代策略是您在 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 次插入/更新后提交

于 2012-10-16T19:50:16.930 回答