Why does Spring Roo give persist() Propogation.REQUIRES_NEW
开发者_如何学运维I've been looking at the code generated by Spring Roo and I noticed that the persist()
method it creates is given Propagation.REQUIRES_NEW
. Wouldn't the default propagation be sufficient?
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void Entity.persist() {
if (this.entityManager == null) this.entityManager = entityManager();
this.entityManager.persist(this);
}
Some additional information. Here is the roo log that produced this code:
// Spring Roo 1.1.0.RELEASE [rev 793f2b0] log opened at 2011-02-04 10:01:02
project --topLevelPackage org.sotest.sscce --projectName Test --java 6
// Spring Roo 1.1.0.RELEASE [rev 793f2b0] log closed at 2011-02-04 10:01:04
// Spring Roo 1.1.0.RELEASE [rev 793f2b0] log opened at 2011-02-04 10:01:06
persistence setup --database GOOGLE_APP_ENGINE --provider DATANUCLEUS
entity --class ~.entities.Entity
exit
// Spring Roo 1.1.0.RELEASE [rev 793f2b0] log closed at 2011-02-04 10:02:55
I am using the GAE database with the DN provider. I simply created an entity, I did not touch any files other than issuing the above roo commands. When I open Entity_Roo_Entity.aj I get the above code.
I will try this again on the latest version of Roo and verify the same output. I will also post this issue on a Roo-related forum.
Update: The same code is generated with Roo 1.1.1 (latest version)
SECOND ANSWER (after additional info was added to question)
It's likely due to the use of GAE. The GAE datastore doesn't use traditional transaction semantics. See description of GAE's transaction isolation here. Specifically:
Queries and gets inside a transaction are guaranteed to see a single, consistent snapshot of the datastore as of the beginning of the transaction. ... This consistent snapshot view also extends to reads after writes inside transactions. Unlike with most databases, queries and gets inside a datastore transaction do not see the results of previous writes inside that transaction. Specifically, if an entity is modified or deleted within a transaction, a query or get returns the original version of the entity as of the beginning of the transaction, or nothing if the entity did not exist then.
There are also restrictions on querying within a transaction. With this in mind, the REQUIRES_NEW is probably added so that any subsequent reads of the entity within the "first" transaction work as expected. Seems confusing and non-standard, but perhaps this is the best option when working in the constraints of GAE.
FIRST ANSWER
There must be a misunderstanding or something else at play. I just checked with Roo v1.1.1 generating a simple entity with Hibernate provider, and the default transaction propagation is used. This is also somewhat verified in the documentation:
All persistence methods are configured with Spring's Transaction support (Propagation.REQUIRED, Isolation.DEFAULT).
Using Propagation.REQUIRES_NEW would not make sense for the default persist methods.
I'm not an expert in Roo, so can't even think of anything that might do this. Perhaps you should post more of your code, particularly any non-standard configurations. Random questions/ideas:
- Are you using Hibernate provider or ?
- Any custom configuration of the persisence-unit?
- Do see the Propagation.REQUIRES_NEW on all of your entity persist methods?
- Where are you seeing the propagation annotation. (e.g. In the *_Entity.aj file?)
Is there any chance that your entity class (or one of it's parents) has it's own .persist method (thus overriding Roo's generated method).
1: http://static.springsource.org/spring-roo/reference/html/base-persistence.html
1: ah. I think it's highly likely to be due to use of the GAE/DN provider. I'll modify my answer accordingly. In the meantime, check out the notes around GAE's transaction isolation here: http://code.google.com/appengine/docs/java/datastore/transactions.html .
精彩评论