@Embeddable with Entity relations [message #729953] |
Tue, 27 September 2011 10:56 |
Luca Graf 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 |
Luca Graf 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 #730813 is a reply to message #730596] |
Thu, 29 September 2011 08:47 |
Luca Graf 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 #730990 is a reply to message #730903] |
Thu, 29 September 2011 16:32 |
Luca Graf 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
|
|
|
|
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.06012 seconds