You are right. But in case of FlushModeType.AUTO there are enormous SQL queries
performed.
This behaviour you mentioned is defined also in Final Release of JSR-000220 Enterprise
JavaBeans 3.0
http://jcp.org/aboutJava/communityprocess/final/jsr220/index.html -
ejb-3_0-fr-spec-persistence.pdf
3.2.3 Synchronization to the Database
anonymous wrote :
| The EntityManager and Query setFlushMode methods can be used to control
synchronization semantics. The effect of FlushModeType.AUTO is defined in section 3.6.2.
If FlushModeType.COMMIT is specified, flushing will occur at transaction commit; the
persistence provider is permitted, but not required, to perform to flush at other times.
If there is no transaction active, the persistence provider must not flush to the
database.
|
and section 3.6.2 Queries and FlushMode
anonymous wrote :
| When queries are executed within a transaction, if FlushModeType.AUTO is set on the
Query object, or if the flush mode setting for the persistence context is AUTO (the
default) and a flush mode setting has not been specified for the Query object, the
persistence provider is responsible for ensuring that all updates to the state of all
entities in the persistence context which could potentially affect the result of the query
are visible to the processing of the query. The persistence provider implementation may
achieve this by flushing those entities to the database or by some other means. If
FlushMode-Type.COMMIT is set, the effect of updates made to entities in the persistence
context upon queries is unspecified.
|
Fortunately I found also in section 3.2.5 Managed Instances
anonymous wrote :
| It is the responsibility of the application to insure that an instance is managed in
only a single persistence context.
| ...
| The contains method returns false:
| . If the remove method has been called on the entity, or the remove operation has been
cascaded to it.
|
SOLUTION: Well my solution for this problem is to check using method
EntityManager.contains(..) that returned object (by EJBQL) is contained in EntityManager
instance.
Changes in my code:
if ((pv.getPlanId() == newDBPlanVersion.getPlanId()) &&
(!pv.equals(newDBPlanVersion)) && em.contains(pv)){
| public DBPlanVersion addPlanVersion(int planId, String description) {
| DBPlanVersion newDBPlanVersion = new DBPlanVersion();
| newDBPlanVersion.setPlanId(planId);
| newDBPlanVersion.setDescription(description);
| // Lets check whether plan version with the same plan id already exists
| for (DBPlanVersion pv : findAll()) {
| if ((pv.getPlanId() == newDBPlanVersion.getPlanId()) &&
(!pv.equals(newDBPlanVersion)) && em.contains(pv)) {
| throw new RuntimeException("Unable to insert plan version with
the same planId = " + pv.getPlanId());
| }
| }
| em.persist(newDBPlanVersion);
| return newDBPlanVersion;
| }
|
It is fully functional also with caching enabled on DBPlanVersion and caching on queries
| @Entity(name = "DBPlanVersion)
| @Table(name = "PLAN_VERSION")
| @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
| @NamedQueries({
| @NamedQuery(name = DBPlanVersion.findAll, query = "SELECT a FROM DBPlanVersion
a", hints = {(a)QueryHint(name="org.hibernate.cacheable",
value="true")}),
| @NamedQuery(name = "DBPlanVersion.findByPlanId, query = "SELECT a FROM
DBPlanVersion a WHERE a.planId = :planId", hints =
{(a)QueryHint(name="org.hibernate.cacheable", value="true")} )
| })
| public static DBPlanVersion implements Serializable {
| // ... the same code as previous post
| }
|
EJB3/JBoss gurus, may I use this solution?
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4146508#...
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&a...