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 nos)。したがって、コードを使用してメソッドを作成できます

@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 に答える