Commit during transaction in @Transactional

天大地大妈咪最大 提交于 2019-12-07 11:02:47

问题


Is that possible to perform commit in the method that is marked as Spring's @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++);
        }
    }
}

I would like to have commit to DB after say each 500 items. Is that possible with aforementioned context?


回答1:


No, you need to do it programatically using, for instance, the TransactionTemplate API. Read more here.

It would look something like

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:


Your question suggests that you have misplaced your transaction boundary.

You can move the persist call into a private method and make that method transactional instead of the outer one. This method could accept 500 members at a time and then will commit when it exits.




回答3:


If you are looking forward to committing transactionally inside your other transaction, you might need to use @Transactional (propagation = Propagation.REQUIRES_NEW)




回答4:


Alternate strategy is you create a method in DAO and mark it @Transactional. This method will do bulk update(for eg 500 nos). So you can have a method with code

@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;
    }
}

Every time you call this method, it will commit after 500 inserts/updates



来源:https://stackoverflow.com/questions/12897882/commit-during-transaction-in-transactional

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!