Community
Participate
Working Groups
> An Entity --> MappedSuperclass(ID1) --> MappedSuperclass(ID2) causes a new ValidationException for a composite PK spread across an inherited MappedSuperclass chain. Why? because we are processing MappedSuperclass descriptors as of rev# 4587 >see http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_78:_20090909:_Composite_.40IdClass_on_inherited_MappedSuperclass_chain_causes_new_ValidationException >reproduction and stacktrace are pending and will be on the wiki
>commit to fix this behavior change by 2.0 >Work on this bug should start around 25 Sept 2009
>starting investigation now
>Starting reproduction 20091111 We are now throwing a validation exception after the metadata changes to preprocess the metamodel descriptors for MappedSuperclasses in the case where there is an @IdClass in a MappedSuperclass above an @Id - this is invalid and used to be ignored. >Note: This occurs only for Id fields - if you remove the single @Id on the center MappedSuperclass - this validation exception does not occur. >Model ------------------------- @MappedSuperclass @IdClass(org.eclipse.persistence.testing.models.jpa.metamodel.MSIdClassPK.class) public abstract class MS_MS_Entity_Root implements java.io.Serializable { @Id @Column(name="TYPE") public String type; @Id @Column(name="LENGTH") protected String length; @Id @Column(name="WIDTH") private String width; } @MappedSuperclass public abstract class MS_MS_Entity_Center extends MS_MS_Entity_Root { > @Id @Column(name="MSMSENTITY_ID") private Integer ident; } @Entity(name="MS_MS_EntityLeafMetamodel") @Table(name="CMP3_MM_MSMSENTITY_LEAF") public class MS_MS_Entity_Leaf extends MS_MS_Entity_Center {} >Table generation ------------------------ // commented code aligns with commented @Id to remove the exception public static TableDefinition buildMS_MS_Entity_Leaf_Table() { TableDefinition table = new TableDefinition(); table.setName("CMP3_MM_MSMSENTITY_LEAF"); // From (MS)-MS-Entity root FieldDefinition field13 = new FieldDefinition(); field13.setName("TYPE"); field13.setTypeName("VARCHAR"); field13.setSize(80); field13.setShouldAllowNull(false); field13.setIsPrimaryKey(true); field13.setUnique(false); field13.setIsIdentity(true); table.addField(field13); FieldDefinition field14 = new FieldDefinition(); field14.setName("LENGTH"); field14.setTypeName("VARCHAR"); field14.setSize(80); field14.setShouldAllowNull(false); field14.setIsPrimaryKey(true); field14.setUnique(false); field14.setIsIdentity(true); table.addField(field14); FieldDefinition field15 = new FieldDefinition(); field15.setName("WIDTH"); field15.setTypeName("VARCHAR"); field15.setSize(80); field15.setShouldAllowNull(false); field15.setIsPrimaryKey(true); field15.setUnique(false); field15.setIsIdentity(true); table.addField(field15); // From MS-(MS)-Entity center FieldDefinition field = new FieldDefinition(); field.setName("MSMSENTITY_ID"); field.setTypeName("NUMERIC"); field.setSize(15); field.setShouldAllowNull(false); //field.setIsPrimaryKey(false);//true); field.setIsPrimaryKey(true); field.setUnique(false); //field.setIsIdentity(false);//true); field.setIsIdentity(true); table.addField(field); FieldDefinition field4 = new FieldDefinition(); field4.setName("MSMSENTITY_VERSION"); field4.setTypeName("NUMERIC"); field4.setSize(15); field4.setShouldAllowNull(true); field4.setIsPrimaryKey(false); field4.setUnique(false); field4.setIsIdentity(false); table.addField(field4); return table; } >Trace ------------------------ javax.persistence.PersistenceException: Exception [EclipseLink-0] (Eclipse Persistence Services - @VERSION@.@QUALIFIER@): org.eclipse.persistence.exceptions.IntegrityException Descriptor Exceptions: --------------------------------------------------------- Exception [EclipseLink-0] (Eclipse Persistence Services - @VERSION@.@QUALIFIER@): org.eclipse.persistence.exceptions.DescriptorException Exception Description: An internal error occurred accessing the primary key object [202]. Internal Exception: java.lang.NoSuchFieldException: ident Descriptor: RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.MS_MS_Entity_Leaf --> [DatabaseTable(CMP3_MM_MSMSENTITY_LEAF)]) Runtime Exceptions: --------------------------------------------------------- at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:390) at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl.java:151) at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:207) at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:195) at org.eclipse.persistence.testing.framework.junit.JUnitTestCase.getServerSession(JUnitTestCase.java:340) at org.eclipse.persistence.testing.framework.junit.JUnitTestCase.getEntityManagerFactory(JUnitTestCase.java:365) at org.eclipse.persistence.testing.framework.junit.JUnitTestCase.getEntityManagerFactory(JUnitTestCase.java:344) at org.eclipse.persistence.testing.tests.jpa.metamodel.MetamodelTest.initialize(MetamodelTest.java:84) at org.eclipse.persistence.testing.tests.jpa.metamodel.MetamodelTest.initialize(MetamodelTest.java:65) at org.eclipse.persistence.testing.tests.jpa.metamodel.MetamodelTest.setUp(MetamodelTest.java:54) at org.eclipse.persistence.testing.tests.jpa.metamodel.MetamodelTest.setUp(MetamodelTest.java:49) at org.eclipse.persistence.testing.tests.jpa.metamodel.EntityManagerFactoryImplTest.setUp(EntityManagerFactoryImplTest.java:46) Exception [EclipseLink-0] (Eclipse Persistence Services - @VERSION@.@QUALIFIER@): org.eclipse.persistence.exceptions.DescriptorException Exception Description: An internal error occurred accessing the primary key object [202]. Internal Exception: java.lang.NoSuchFieldException: ident Descriptor: RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.metamodel.MS_MS_Entity_Leaf --> [DatabaseTable(CMP3_MM_MSMSENTITY_LEAF)]) Runtime Exceptions: --------------------------------------------------------- at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:478) at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:406) at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.postConnectDatasource(DatabaseSessionImpl.java:671) at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.login(DatabaseSessionImpl.java:633) at org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:230) at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:366) >This is an invalid configuration - I recommend we let this warning occur in our new MappedSuperclass descriptor validation - and not suppress it.
>However, we should temporarily suspend validation for pseudo MappedSuperclass Descriptor partial processing (no initialization - is why we do not find the field yet) - during stage 2 in MetadataProject.processStage2() for m_metamodelMappedSuperclasses
Created attachment 152478 [details] DI 78: This patch is for community reference and discussion only - a final revised patch will be submitted for review before checkin
Created attachment 152547 [details] DI 78: This patch is for community reference and discussion only - a final revised patch will be submitted for review before checkin >Added more granular truncation of initialization in ObjectBuilder for MappedSuperclass defined id mappings
Created attachment 152584 [details] DI 78: skip initialization of @Id mappings declared above on MappedSuperclass chains during Entity deploy() processing in ClassDescriptor and ObjectBuilder : pre-code review
Created attachment 152673 [details] DI 78: Code review 1 Problem summary: ------------------ When we have a composite PK IdClass defined where the id mappings are spread across 2 or more MappedSuperclasses in an inheritance tree, we are unable to initialize the id mappings on the center mappedSuperclass because the other inherited id mappings are only copied to the first Entity leaf in the chain (and skip the middle mappedSuperclass). We will - add isJPAIdClass field to DatabaseMapping - so we don't have to search the IdClassMap on the core project - add isMappedSuperclassMapping to store the accessor type on the DatabaseMapping - only skip Id initialization if all the id's are not defined on the current MappedSuperclass TEST MODEL NAME: (JUnit test): Metamodel Errors: (failures): 0 Fatal Errors: (errors): 0 Passed: 124 Total Tests: 124 TEST MODEL NAME: (JUnit test): Criteria Errors: (failures): 0 Fatal Errors: (errors): 0 Passed: 134 Total Tests: 134
Created attachment 152821 [details] original model invalid - adjusted test model has no issues >20091122 the model is wrong. We must ensure that we have access to the IdClass attribute where we define @IdClass. In the case of the model above - the 4th @Id on the middle subclass mappedSuperclass is not accessible from the top root. >Model ------------------------- @MappedSuperclass @IdClass(org.eclipse.persistence.testing.models.jpa.metamodel.MSIdClassPK.class) // invalid - should be one level down public abstract class MS_MS_Entity_Root implements java.io.Serializable { @Id protected String type; @Id protected String length; @Id protected String width; } @MappedSuperclass public abstract class MS_MS_Entity_Center extends MS_MS_Entity_Root { > @Id protected Integer ident; } @Entity(name="MS_MS_EntityLeafMetamodel") public class MS_MS_Entity_Leaf extends MS_MS_Entity_Center {} >should be >Model ------------------------- @MappedSuperclass public abstract class MS_MS_Entity_Root implements java.io.Serializable { @Id protected String type; @Id protected String length; @Id protected String width; } @MappedSuperclass @IdClass(org.eclipse.persistence.testing.models.jpa.metamodel.MSIdClassPK.class) // or defined on the entity public abstract class MS_MS_Entity_Center extends MS_MS_Entity_Root { > @Id protected Integer ident; } @Entity(name="MS_MS_EntityLeafMetamodel") public class MS_MS_Entity_Leaf extends MS_MS_Entity_Center {}
>Invalid model - bug closed and test model fixed. It turns out that the reproduction model for an IdClass distributed among multiple MappedSuperclasses was incorrect. There were two issues: 1) the IdClass itself only defined 3 or the 4 Id attributes and 2) the @IdClass annotation should have been either 1 or 2 levels down on the center MappedSuperclass or the leaf Entity. The result of this was I was trying to suppress a valid integrity warning on the missing id that was not visible from the top root MappedSuperclass. After discussing this with 4 senior members of my JPA team I see that the integrity of the IdClass drives the placement of the @IdClass annotation. http://fisheye2.atlassian.com/changelog/eclipselink/?cs=5849
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink