问题
I am using Spring 3, JPA + Hibernate for a CMS
application. In that application I have a service class method which is annotated with @Transactional
Annotation with rollBack
property. Inside that method I am inserting data (ie entity classes) to a table using a loop. For each iteration
of the loop entity classes has to be saved to the database. But it is not happening. The commit only happens when the execution of the loop has completed and exits from the method. Then it commits and saves all at once. But I need to read data once it gets inserted into the database before committing in this case. I tried with the ISOLATION LEVEL
to read uncommitted but it didn't supported since I am using the default JPADialect
. Also tried to add the hibernate implementation of jpaDialect
but still it didn't worked. Please help with a workaround for this problem. One more thing, is there any way using propagation required method.
回答1:
remove the transactional annoation on the the method with loop.
In the loop call a separate method to perform the save, make that method transactional
回答2:
You are right, this is what I
stands for in acid. Because the transactions are working in isolation, other transactions cannot see them before they are committed. But playing with isolation levels is a bad practice. I would rather advice you to run each and every iteration in a separate transaction with start and commit inside.
This is a bit tricky in Spring, but here is an example:
public void batch() {
for(...) {
insert(...)
}
}
//necessarily in a different class!
@Transactional
public void insert() {
}
Note that batch()
is not annotated with @Transactional
and insert()
has to be in a different class (Spring service). Too long to comment, but that's life. If you don't like it, you can use TransactionTemplate
manually.
回答3:
You either need to go with programmatic transactions (Spring's TransactionTemplate
or PlatformTransactionManager
are the classes to look at, see Spring Doc for programmatic transactions, or you can call another transactional method from within your loop where the transaction is marked with Propagation.REQUIRES_NEW
, meaning each call of that method is executed in its own transaction, see here. I think that the second approach requires you to define the REQUIRES_NEW method on a different Spring bean because of the AOP-Proxy. You can also omit the REQUIRES_NEW if the loop is not executed within a transaction.
来源:https://stackoverflow.com/questions/9721004/transactional-annotation-for-a-data-insertion-in-a-loop