Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » @Embeddable with Entity relations(Mapping behaves strange when used in a Set )
@Embeddable with Entity relations [message #729953] Tue, 27 September 2011 10:56 Go to next message
Luca Graf is currently offline Luca GrafFriend
Messages: 17
Registered: September 2011
Junior Member
Hi,

i struggle with a strange issue when i use @Embeddable objects that holds a reference to an Entity.

Example:

I have a parent object, that holds a collection of Embeddables (in a Set)
@Entity
public class Parent implements Serializable {
   @Id
   @GeneratedValue( strategy = GenerationType.AUTO )
   private Long id;

   @ElementCollection
   @CollectionTable( joinColumns = @JoinColumn( name = "parent_id", nullable = false ) )
   private Set<Child> children = new HashSet<Child>();
   ...
}


The Embeddable holds a reference to an Entity.
@Embeddable
public class Child implements Serializable {
   @ManyToOne( optional = false )
   private EntityRelation entityRelation;
   ...
}	


The reference Entity
@Entity
public class EntityRelation implements Serializable {
   @Id
   @GeneratedValue( strategy = GenerationType.AUTO )
   private Long id;
   ...
}


Under some circumstances[1] EclipseLink tries to insert already existent (in the database) EntityRelation objects what ends up in duplicate key exceptions.


After a bit of research i found this in the JPA 2 spec (Section 2.5):

Quote:

An embeddable class may contain a relationship to an entity or collection of entities.
Since instances of embeddable classes themselves have no persistent identity, the relationship from the referenced entity is to the entity that contains the embeddable instance(s) and not to the embeddable itself.[17]
An embeddable class that is used as an embedded id or as a map key must not contain such a relationship.


Iam not sure, but this also implies that such a mapping can't be used in sets like in the example above?


Greetings Luca

[1] For readability i will describe the use case more detailed in a new posting.

[Updated on: Tue, 27 September 2011 13:05]

Report message to a moderator

Re: @Embeddable with Entity relations [message #729955 is a reply to message #729953] Tue, 27 September 2011 10:58 Go to previous messageGo to next message
Luca Graf is currently offline Luca GrafFriend
Messages: 17
Registered: September 2011
Junior Member
Environment:

Linux
Glassfish 3.1 (Eclipse Persistence Services - 2.2.0.v20110202-r8913)


Use case (pseudo code):

List<Parent> parents = ps.getAllParents(); //load parents
for( Parent parent : parents ) {
   IndependentEntity ie = is.selectOrCreate( -1L ); //selects an independent entity or returns a new (transient)
   for( Child child : parent.getChildren() ) {
      child.getEntityRelation();
   }
   is.merge( ie );
}


If there (at minimum) two parents this code will fail with a duplicate key exception at flush/commit time.
Note, the code above not change anything on the Child/EntityRelation objects.
It seems that this only happens if another Entity will persisted/updated in the same transaction.

Log:
FEINER: client acquired: 1953950842
FEINER: TX binding to tx mgr, status=STATUS_ACTIVE
FEINER: acquire unit of work: 731871570
FEINER: begin unit of work flush
FEINER: end unit of work flush
AM FEINSTEN: Execute query ReadAllQuery(name="findAllParents" referenceClass=Parent sql="SELECT ID FROM PARENT ORDER BY ID ASC")
AM FEINSTEN: Connection acquired from connection pool [read].
AM FEINSTEN: reconnecting to external connection pool
FEIN: SELECT ID FROM PARENT ORDER BY ID ASC
AM FEINSTEN: Connection released to connection pool [read].
AM FEINSTEN: Execute query ReadObjectQuery(name="readObject" referenceClass=IndependentEntity sql="SELECT ID FROM INDEPENDENTENTITY WHERE (ID = ?)")
AM FEINSTEN: Connection acquired from connection pool [read].
AM FEINSTEN: reconnecting to external connection pool
FEIN: SELECT ID FROM INDEPENDENTENTITY WHERE (ID = ?)
	bind => [-1]
AM FEINSTEN: Connection released to connection pool [read].
AM FEINSTEN: Execute query ReadAllQuery(name="children" referenceClass=Child sql="SELECT CHILDNAME, entityrelation_id, parent_id FROM Parent_CHILDREN WHERE (parent_id = ?)")
AM FEINSTEN: Connection acquired from connection pool [read].
AM FEINSTEN: reconnecting to external connection pool
FEIN: SELECT CHILDNAME, entityrelation_id, parent_id FROM Parent_CHILDREN WHERE (parent_id = ?)
	bind => [1]
AM FEINSTEN: Connection released to connection pool [read].
AM FEINSTEN: Execute query ReadObjectQuery(name="entityRelation" referenceClass=EntityRelation )
AM FEINSTEN: Connection acquired from connection pool [read].
AM FEINSTEN: reconnecting to external connection pool
FEIN: SELECT ID, RELATIONNAME, RELATIONTYPE FROM ENTITYRELATION WHERE (ID = ?)
	bind => [1]
AM FEINSTEN: Connection released to connection pool [read].
AM FEINSTEN: Execute query ReadObjectQuery(name="entityRelation" referenceClass=EntityRelation )
AM FEINSTEN: Connection acquired from connection pool [read].
AM FEINSTEN: reconnecting to external connection pool
FEIN: SELECT ID, RELATIONNAME, RELATIONTYPE FROM ENTITYRELATION WHERE (ID = ?)
	bind => [2]
AM FEINSTEN: Connection released to connection pool [read].
AM FEINSTEN: Execute query ReadObjectQuery(name="entityRelation" referenceClass=EntityRelation )
AM FEINSTEN: Connection acquired from connection pool [read].
AM FEINSTEN: reconnecting to external connection pool
FEIN: SELECT ID, RELATIONNAME, RELATIONTYPE FROM ENTITYRELATION WHERE (ID = ?)
	bind => [3]
AM FEINSTEN: Connection released to connection pool [read].
AM FEINSTEN: Register the object org.test.entity.EntityRelation@46cd0462
AM FEINSTEN: Register the object org.test.entity.EntityRelation@ec94549f
AM FEINSTEN: Register the object org.test.entity.EntityRelation@4ecb5266
AM FEINSTEN: Merge clone with references org.test.entity.IndependentEntity@560fc912
FEINER: TX beginTransaction, status=STATUS_ACTIVE
AM FEINSTEN: Connection acquired from connection pool [default].
AM FEINSTEN: Execute query DataModifyQuery(name="SEQUENCE" sql="UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + #PREALLOC_SIZE WHERE SEQ_NAME = #SEQ_NAME")
AM FEINSTEN: reconnecting to external connection pool
FEIN: UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
	bind => [50, SEQ_GEN]
AM FEINSTEN: Execute query ValueReadQuery(name="SEQUENCE" sql="SELECT SEQ_COUNT FROM SEQUENCE WHERE SEQ_NAME = #SEQ_NAME")
FEIN: SELECT SEQ_COUNT FROM SEQUENCE WHERE SEQ_NAME = ?
	bind => [SEQ_GEN]
AM FEINSTEN: local sequencing preallocation for SEQ_GEN: objects: 50 , first: 51, last: 100
AM FEINSTEN: assign sequence to the object (51 -> org.test.entity.IndependentEntity@2659e8e2)
FEINER: begin unit of work flush
FEINER: TX beginTransaction, status=STATUS_ACTIVE
AM FEINSTEN: Execute query InsertObjectQuery(org.test.entity.IndependentEntity@2659e8e2)
FEIN: INSERT INTO INDEPENDENTENTITY (ID) VALUES (?)
	bind => [51]
AM FEINSTEN: Execute query UpdateObjectQuery(org.test.entity.Parent@1)
AM FEINSTEN: Execute query UpdateObjectQuery(org.test.entity.Child@46cd0709)
AM FEINSTEN: Execute query UpdateObjectQuery(org.test.entity.Child@4ecb550d)
AM FEINSTEN: Execute query UpdateObjectQuery(org.test.entity.Child@ec945746)
FEINER: end unit of work flush
FEINER: resume unit of work
AM FEINSTEN: Execute query ReadObjectQuery(name="readObject" referenceClass=IndependentEntity sql="SELECT ID FROM INDEPENDENTENTITY WHERE (ID = ?)")
FEIN: SELECT ID FROM INDEPENDENTENTITY WHERE (ID = ?)
	bind => [-1]
AM FEINSTEN: Execute query ReadAllQuery(name="children" referenceClass=Child sql="SELECT CHILDNAME, entityrelation_id, parent_id FROM Parent_CHILDREN WHERE (parent_id = ?)")
AM FEINSTEN: Execute query ReadAllQuery(name="children" referenceClass=Child sql="SELECT CHILDNAME, entityrelation_id, parent_id FROM Parent_CHILDREN WHERE (parent_id = ?)")
FEIN: SELECT CHILDNAME, entityrelation_id, parent_id FROM Parent_CHILDREN WHERE (parent_id = ?)
	bind => [2]
AM FEINSTEN: Execute query ReadObjectQuery(name="entityRelation" referenceClass=EntityRelation )
AM FEINSTEN: Execute query ReadObjectQuery(name="entityRelation" referenceClass=EntityRelation )
AM FEINSTEN: Execute query ReadObjectQuery(name="entityRelation" referenceClass=EntityRelation )rge IndependentEntity ...
AM FEINSTEN: Merge clone with references org.test.entity.IndependentEntity@1703c2db
AM FEINSTEN: assign sequence to the object (52 -> org.test.entity.IndependentEntity@77edc3aa)
FEINER: begin unit of work flush
AM FEINSTEN: Execute query DoesExistQuery(referenceClass=EntityRelation )
AM FEINSTEN: Execute query DoesExistQuery(referenceClass=EntityRelation )
AM FEINSTEN: Execute query DoesExistQuery(referenceClass=EntityRelation )
AM FEINSTEN: Execute query InsertObjectQuery(org.test.entity.IndependentEntity@77edc3aa)
FEIN: INSERT INTO INDEPENDENTENTITY (ID) VALUES (?)
	bind => [52]
AM FEINSTEN: Execute query UpdateObjectQuery(org.test.entity.Parent@1)
AM FEINSTEN: Execute query UpdateObjectQuery(org.test.entity.Child@46cd0709)
AM FEINSTEN: Execute query UpdateObjectQuery(org.test.entity.Child@4ecb550d)
AM FEINSTEN: Execute query UpdateObjectQuery(org.test.entity.Child@ec945746)
AM FEINSTEN: Execute query UpdateObjectQuery(org.test.entity.Parent@2)
AM FEINSTEN: Execute query UpdateObjectQuery(org.test.entity.Child@46cd0709)
AM FEINSTEN: Execute query WriteObjectQuery(org.test.entity.EntityRelation@46cd0462)
FEIN: INSERT INTO ENTITYRELATION (ID, RELATIONNAME, RELATIONTYPE) VALUES (?, ?, ?)
	bind => [2, relation2, INTEGER_T]
FEIN: SELECT 1
WARNUNG: Local Exception Stack: 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: FEHLER: doppelter Schlüsselwert verletzt Unique-Constraint »entityrelation_pkey«
Error Code: 0
Call: INSERT INTO ENTITYRELATION (ID, RELATIONNAME, RELATIONTYPE) VALUES (?, ?, ?)
	bind => [2, relation2, INTEGER_T]
Query: WriteObjectQuery(org.test.entity.EntityRelation@46cd0462)
	at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.processExceptionForCommError(DatabaseAccessor.java:1420)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:796)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:864)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:583)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:526)
	at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1729)
	at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:234)
	at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:207)
	at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:193)
	at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:342)
	at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:162)
	at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:177)
	at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:469)
	at org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:80)
	at org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:90)
	at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.performUserDefinedWrite(DatabaseQueryMechanism.java:561)
	at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.performUserDefinedInsert(DatabaseQueryMechanism.java:529)
	at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:399)
	at org.eclipse.persistence.queries.WriteObjectQuery.executeCommitWithChangeSet(WriteObjectQuery.java:121)
	at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:291)
	at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
	at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:808)
	at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:711)
	at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
	at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2842)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1521)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1503)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1463)
	at org.eclipse.persistence.mappings.ObjectReferenceMapping.update(ObjectReferenceMapping.java:1111)
	at org.eclipse.persistence.mappings.ObjectReferenceMapping.preUpdate(ObjectReferenceMapping.java:590)
	at org.eclipse.persistence.descriptors.DescriptorQueryManager.preUpdate(DescriptorQueryManager.java:1095)
	at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.updateObjectForWrite(DatabaseQueryMechanism.java:993)
	at org.eclipse.persistence.queries.UpdateObjectQuery.executeCommit(UpdateObjectQuery.java:69)
	at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWrite(DatabaseQueryMechanism.java:236)
	at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:60)
	at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:808)
	at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:711)
	at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
	at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2842)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1521)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1503)
	at org.eclipse.persistence.mappings.AggregateCollectionMapping.objectUnchangedDuringUpdate(AggregateCollectionMapping.java:2024)
	at org.eclipse.persistence.mappings.CollectionMapping.compareObjectsAndWrite(CollectionMapping.java:700)
	at org.eclipse.persistence.mappings.AggregateCollectionMapping.postUpdate(AggregateCollectionMapping.java:2118)
	at org.eclipse.persistence.descriptors.DescriptorQueryManager.postUpdate(DescriptorQueryManager.java:995)
	at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.updateObjectForWriteWithChangeSet(DatabaseQueryMechanism.java:1175)
	at org.eclipse.persistence.queries.UpdateObjectQuery.executeCommitWithChangeSet(UpdateObjectQuery.java:84)
	at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:291)
	at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
	at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:808)
	at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:711)
	at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
	at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2842)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1521)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1503)
	at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1463)
	at org.eclipse.persistence.internal.sessions.CommitManager.commitChangedObjectsForClassWithChangeSet(CommitManager.java:265)
	at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsForClassWithChangeSet(CommitManager.java:190)
	at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:136)
	at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:3766)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1404)
	at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:616)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithPreBuiltChangeSet(UnitOfWorkImpl.java:1552)
	at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.writeChanges(RepeatableWriteUnitOfWork.java:427)
	at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:744)
	at com.sun.enterprise.container.common.impl.EntityManagerWrapper.flush(EntityManagerWrapper.java:418)
	at org.test.service.IndependentEntityService.merge(IndependentEntityService.java:37)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
	at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
	at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5367)
	at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:619)
	at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:801)
	at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
	at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:162)
	at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:144)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:862)
	at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:801)
	at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:371)
	at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5339)
	at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5327)
	at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:214)
	at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
	at $Proxy129.merge(Unknown Source)
	at org.test.service.__EJB31_Generated__IndependentEntityService__Intf____Bean__.merge(Unknown Source)
	at org.test.timer.Runner.run(Runner.java:51)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
	at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
	at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5367)
	at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:619)
	at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:801)
	at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
	at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:162)
	at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundTimeout(SystemInterceptorProxy.java:149)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:862)
	at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:801)
	at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:371)
	at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5339)
	at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5327)
	at com.sun.ejb.containers.BaseContainer.callEJBTimeout(BaseContainer.java:4033)
	at com.sun.ejb.containers.EJBTimerService.deliverTimeout(EJBTimerService.java:1835)
	at com.sun.ejb.containers.EJBTimerService.access$100(EJBTimerService.java:108)
	at com.sun.ejb.containers.EJBTimerService$TaskExpiredWork.run(EJBTimerService.java:2708)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:662)
Caused by: org.postgresql.util.PSQLException: FEHLER: doppelter Schlüsselwert verletzt Unique-Constraint »entityrelation_pkey«
	at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2103)
	at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1836)
	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:512)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:388)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:334)
	at com.sun.gjc.spi.base.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:120)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:789)
	... 125 more

[Updated on: Tue, 27 September 2011 14:47]

Report message to a moderator

Re: @Embeddable with Entity relations [message #730548 is a reply to message #729955] Wed, 28 September 2011 15:33 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1039
Registered: July 2009
Senior Member
Hello,

It appears from the log that Child@46cd0709 is in both Parent1 and Parent2. Each parent should have its own instance, and instead share a reference to the EntityRelation instance. By sharing the embeddable, this is confusing the change processing.

Best Regards,
Chris
Re: @Embeddable with Entity relations [message #730596 is a reply to message #729955] Wed, 28 September 2011 15:33 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1039
Registered: July 2009
Senior Member
Hello,

It appears from the log that Child@46cd0709 is in both Parent1 and Parent2. Each parent should have its own instance, and instead share a reference to the EntityRelation instance. By sharing the embeddable, this is confusing the change processing.

Best Regards,
Chris
Re: @Embeddable with Entity relations [message #730813 is a reply to message #730596] Thu, 29 September 2011 08:47 Go to previous messageGo to next message
Luca Graf is currently offline Luca GrafFriend
Messages: 17
Registered: September 2011
Junior Member
Hi Chris,

thanks for your commenting on this. I think you are right with your assumption, but I don't know how to avoid this. The Children are implicitly loaded/created by eclipselink (parent.getChildren()).

I think the problem is the implementation of the equals/hashCode methods in the Child class.

public final boolean equals( Object obj ) {
   if( obj == null )
      return false;
   if( getClass() != obj.getClass() )
      return false;
   final Child other = ( Child ) obj;
   if( this.entityRelation != other.entityRelation && (this.entityRelation == null || !this.entityRelation.equals( other.entityRelation )) )
      return false;
   return true;
}

public final int hashCode() {
   int hash = 7;
   hash = 97 * hash + (this.entityRelation != null ? this.entityRelation.hashCode() : 0);
   return hash;
}


In my application Child classes are equal if they reference the same EntityRelation object.
This works fine in most of the cases. Normally childs are only used in the context of the parent.

Unlike in the example of the previous post where childs of different parents are used (accessed) together (in the same transaction/persistencecontext).
I'm not sure if at this point my equals/hashCode implementation is meaningful enough for eclipselink.

Put another way, do I need the parent as additional information in my Child class to implement an equals method that also takes the Parent into account?
Is this required by eclipselink?


Thanking you in anticipation,
Luca

[Updated on: Thu, 29 September 2011 09:01]

Report message to a moderator

Re: @Embeddable with Entity relations [message #730900 is a reply to message #730813] Thu, 29 September 2011 13:41 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1039
Registered: July 2009
Senior Member
I am not sure they are used by EclipseLink, but you can try testing with the default hashcode and equals to verify. What I was suggesting though was that the problem might be in the initially setting Parent->Child relation. Two parents should not be set to reference the same embeddable child object.

Best Regards,
Chris
Re: @Embeddable with Entity relations [message #730903 is a reply to message #730813] Thu, 29 September 2011 13:41 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1039
Registered: July 2009
Senior Member
I am not sure they are used by EclipseLink, but you can try testing with the default hashcode and equals to verify. What I was suggesting though was that the problem might be in the initially setting Parent->Child relation. Two parents should not be set to reference the same embeddable child object.

Best Regards,
Chris
Re: @Embeddable with Entity relations [message #730990 is a reply to message #730903] Thu, 29 September 2011 16:32 Go to previous messageGo to next message
Luca Graf is currently offline Luca GrafFriend
Messages: 17
Registered: September 2011
Junior Member
I have tested it also with default Object equals/hashCode implementation, but the same duplicate-key exception was thrown.

I realized also, that the default Object toString() method use the hashCode() method internal, so the output in the log (assuming eclipelink use toString()) must not indicate that the objects are the same in the sense of identity.

Output when Object equals/hashCode is used:
...
FEINER: begin unit of work flush
AM FEINSTEN: Execute query DoesExistQuery(referenceClass=EntityRelation )
AM FEINSTEN: Execute query DoesExistQuery(referenceClass=EntityRelation )
AM FEINSTEN: Execute query DoesExistQuery(referenceClass=EntityRelation )
AM FEINSTEN: Execute query InsertObjectQuery(org.test.entity.IndependentEntity@5593d23b)
FEIN: INSERT INTO INDEPENDENTENTITY (ID) VALUES (?)
	bind => [52]
AM FEINSTEN: Execute query UpdateObjectQuery(org.test.entity.Parent@1)
AM FEINSTEN: Execute query UpdateObjectQuery(org.test.entity.Child@42b9f649)
AM FEINSTEN: Execute query UpdateObjectQuery(org.test.entity.Child@5ad2ee0f)
AM FEINSTEN: Execute query UpdateObjectQuery(org.test.entity.Child@248bf20b)
AM FEINSTEN: Execute query UpdateObjectQuery(org.test.entity.Parent@2)
AM FEINSTEN: Execute query UpdateObjectQuery(org.test.entity.Child@4440096c)
AM FEINSTEN: Execute query WriteObjectQuery(org.test.entity.EntityRelation@5fbfc2eb)
FEIN: INSERT INTO ENTITYRELATION (ID, RELATIONNAME, RELATIONTYPE) VALUES (?, ?, ?)
	bind => [1, relation1, STRING_T]
FEIN: SELECT 1
WARNUNG: Local Exception Stack: 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: FEHLER: doppelter Schlüsselwert verletzt Unique-Constraint »entityrelation_pkey«
Error Code: 0
Call: INSERT INTO ENTITYRELATION (ID, RELATIONNAME, RELATIONTYPE) VALUES (?, ?, ?)
	bind => [1, relation1, STRING_T]
Query: WriteObjectQuery(org.test.entity.EntityRelation@5fbfc2eb)
...


Iam not sure but i think there should be no problem with the initial Parent->Child relation. The relation is already persisted and i use a new transaction/persistencecontext to lookup the parents.

That is the database content for the testcase:
select * from parent;
id
----
1
2
(2 rows)


select * from parent_children;
entityrelation_id | childname | parent_id
-------------------+-----------+-----------
1                 | child1    |         1
2                 | child2    |         1
3                 | child3    |         1
1                 | child4    |         2
2                 | child5    |         2
3                 | child6    |         2
(6 rows)


select * from entityrelation;
id | relationname | relationtype
----+--------------+--------------
1 | relation1    | STRING_T
2 | relation2    | INTEGER_T
3 | relation3    | DATE_T
(3 rows)


select * from independententity;
id
----
(0 rows)


select * from sequence;
seq_name | seq_count
----------+-----------
SEQ_GEN  |        50
(1 row)


Greetings Luca

[Updated on: Thu, 29 September 2011 16:49]

Report message to a moderator

Re: @Embeddable with Entity relations [message #731272 is a reply to message #730990] Fri, 30 September 2011 13:37 Go to previous messageGo to next message
Gordon Yorke is currently offline Gordon YorkeFriend
Messages: 77
Registered: July 2009
Member
It is unlikely that the issue has to do with HashCode or Equals. Internally EclipseLink uses system identity to track Entities and changes to Entities.

It is possible it may be this issue:https://bugs.eclipse.org/bugs/show_bug.cgi?id=300108

Otherwise I recommend filing a bug and attaching a small testcase.

[Updated on: Fri, 30 September 2011 14:17]

Report message to a moderator

Re: @Embeddable with Entity relations [message #731280 is a reply to message #730990] Fri, 30 September 2011 13:37 Go to previous messageGo to next message
Gordon Yorke is currently offline Gordon YorkeFriend
Messages: 77
Registered: July 2009
Member
This entry was entered erroneously

[Updated on: Fri, 30 September 2011 14:18]

Report message to a moderator

Re: @Embeddable with Entity relations [message #731292 is a reply to message #731280] Fri, 30 September 2011 14:28 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1039
Registered: July 2009
Senior Member
Hello,

Please file a bug with a test case for this issue. Can you also try making the Child an Entity just for testing? This would mean changing the Parent->Child to a 1:M with a Child->Parent relationship used as the Child's ID.

Best Regards,
Chris
Re: @Embeddable with Entity relations [message #732225 is a reply to message #729953] Tue, 04 October 2011 09:40 Go to previous messageGo to next message
Luca Graf is currently offline Luca GrafFriend
Messages: 17
Registered: September 2011
Junior Member
I implemented a small sample that can be executed as junit test (using hsql).
The project can be found on github: 'https://github.com/lgraf/eclipselink-test/tree/base-test'. I also attached it to this post (eclipselink-test.zip).

While implementing I realized that the problem seemed to be non-deterministic (the test fails only 'most' of the time).

But I think I got new insights:
1. The problem seems to occur only if repeated calls to flush() are made. I thought this was not relevant to the problem through some testing before.
2. It is not neccessary to insert/merge an entity to reproduce the problem.

But due to the non-deterministic behaviour I'm not 100% sure about that.

The code to reproduce now looks like:
List<Parent> parents = em.createNamedQuery( "findAllParents", Parent.class ).getResultList();
for ( Parent parent : parents ) {
   for ( Child child : parent.getChildren() ) {
      child.getEntityRelation();
   }
   em.flush(); // seems to be the problem ...
}

I'm not sure if subsequent calls to flush() could be a problem?
I researched a bit on that (spec/javadoc) but couldn't find any sources saying it would be dangerous.


@Chris: The test project contains a case where the children are implemented as 1-n entity mapping (tag: entity-mapping-test). It seems this test passes all the time. But because the other test behaves non-deterministic, I wouldn't wanna swear on it.


[1] Some notes on the repo:
1. There's a tag 'base-test' that contains code/tests to reproduce the problem.
2. There's a tag 'entity-mapping-test' that includes an additional example with entities using an 1-n 'entity mapping' to build the parent->child relation (including a test) like suggested by Chris.

For simplicity the 'base-test' tag should be used as a starting point.


So, that was a lots of info. I hope this will help to track this issue down.
I will wait a few days, maybe the discussion here will bring up a solution. Otherwise I will open an issue.

Thanks for your support!
Luca


P.S. Because of deadlines in our project we decided to implement the relation using a List instead of a Set. This also seems to workaround the issue.
Re: @Embeddable with Entity relations [message #732232 is a reply to message #729953] Tue, 04 October 2011 09:40 Go to previous messageGo to next message
Luca Graf is currently offline Luca GrafFriend
Messages: 17
Registered: September 2011
Junior Member
This entry was entered erroneously

[Updated on: Tue, 04 October 2011 10:15]

Report message to a moderator

Re: @Embeddable with Entity relations [message #732244 is a reply to message #731272] Tue, 04 October 2011 10:11 Go to previous message
Luca Graf is currently offline Luca GrafFriend
Messages: 17
Registered: September 2011
Junior Member
Gordon Yorke wrote on Fri, 30 September 2011 15:37

...
It is possible it may be this issue:https://bugs.eclipse.org/bugs/show_bug.cgi?id=300108


I'm not sure if this is the same issue.
When i execute the test against the latest 2.4.0-SNAPSHOT a different exception will be thrown:
java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: org.test.entity.EntityRelation@2d28762e.
	at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.discoverUnregisteredNewObjects(RepeatableWriteUnitOfWork.java:304)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:702)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1490)
	at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:267)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1143)
	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:84)
	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63)
	at org.test.usecase.DuplicateKeyCaseTest.cleanUpDBInOwnTransaction(DuplicateKeyCaseTest.java:116)
	at org.test.usecase.DuplicateKeyCaseTest.commitTransactionAndCleanUpDB(DuplicateKeyCaseTest.java:54)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:37)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

This looks like another error (but it may related), it occours in a other place (in the transaction which is executed after the test for cleaning up the database). You can easily reproduce this by changing the eclipselink-version in test projects pom.xml.

Please note that the problem seems to be also non-deterministic.

Greetings Luca
Previous Topic:Multi-tenancy and @PersistenceContext
Next Topic:Composite Persistence and OSGi ?
Goto Forum:
  


Current Time: Mon Dec 22 20:48:41 GMT 2014

Powered by FUDForum. Page generated in 0.09936 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software