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?
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++);
}
}
);
}
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.
If you are looking forward to committing transactionally inside your other transaction, you might need to use @Transactional (propagation = Propagation.REQUIRES_NEW)
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