在@Transactional交易期间提交

时间:2012-10-15 14:34:20

标签: spring hibernate jpa transactions transactional

是否可以在标记为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 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分: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++);
            }
        }
    );
}

答案 2 :(得分:1)

如果您期望在其他交易中进行交易,则可能需要使用@Transactional (propagation = Propagation.REQUIRES_NEW)

答案 3 :(得分:-1)

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

相关问题