Community
Participate
Working Groups
>This issue was found when adding seconary handlers for DI 98 for the specific use case when the @MapKey name attribute is not specified and the Map<K,V> generics define a Basic (DirectToField) Mapping. Currently there is a functionaly workaround in the MapAttributeImpl constructor to secondarily get the attributeClassification on the accessor. >See UC1a and UC7 in http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_98:_20091109:_MapAttribute_keyType_processing_should_offload_more_to_MappedKeyContainerPolicy.keyMapping >Model --------------------------- // UC 7: Generics KV set, targetEntity is also set, @MapKey is *(set/unset) // Same as UC1a - that is missing the @MapKey @OneToMany(targetEntity=HardwareDesigner.class, cascade=ALL, mappedBy="mappedEmployerUC7") private Map<String, HardwareDesigner> hardwareDesignersMapUC7; or // UC 1a: Generics KV set, no @MapKey present, PK is singular field @OneToMany(cascade=ALL, mappedBy="mappedEmployerUC1a") private Map<String, HardwareDesigner> hardwareDesignersMapUC1a; >Workaround --------------------------- if(policy.isMapPolicy()) { // There is always a MapPolicy // check for Either a generic Map (MapContainerPolicy) or specific MappedKeyMapContainerPolicy subclass if(policy.isMappedKeyMapPolicy()) { // The cast below is unavoidable because getKeyMapping() is not overridden from the MapContainerPolicy superclass keyMapping = ((MappedKeyMapContainerPolicy)policy).getKeyMapping(); -->normal policyKeyType = keyMapping.getMapKeyTargetType(); // DirectToFieldMapping implements MapKeyMapping - here we get the key from the attributeClassification if(null == policyKeyType) { -->workaround policyKeyType = ((DatabaseMapping)keyMapping).getAttributeClassification(); >Why -------------------------- Normally we process the MappedKeyMapContainerPolicy.keyMapping.attributeAccessor.attributeField, however in this Basic/DirectToField case we should also be checking the attributeClassification on the accessor. Since the Metamodel API is the only user of this functionaly so far - the workaround is in the MapAttributeImpl constructor - but it should be moved up into AbstractDirectMapping in the Foundation API keyMapping DirectToFieldMapping (id=280) attributeAccessor InstanceVariableAttributeAccessor (id=291) > attributeField null attributeName null isReadOnly false isWriteOnly false > attributeClassification Class<T> (java.lang.String) (id=95) attributeClassificationName "java.lang.String" (id=209) attributeName null attributeObjectClassification null converter null converterClassName null derivedIdMapping null derivesId false descriptor RelationalDescriptor (id=113) field DatabaseField (id=293) fields Vector<E> (id=294) isJPAId false isLazy null isMapKeyMapping true isMutable null isOptional true isPrimaryKeyMapping false isReadOnly false isRemotelyInitialized false keyTableForMapKey DatabaseTable (id=215) mapsIdValue null nullValue null properties null weight Integer (id=216) policy MappedKeyMapContainerPolicy (id=118) cloneMethod null constructor Constructor<T> (id=160) containerClass Class<T> (org.eclipse.persistence.indirection.IndirectMap) (id=88) containerClassName null elementClass Class<T> (org.eclipse.persistence.testing.models.jpa.metamodel.HardwareDesigner) (id=121) elementClassName "org.eclipse.persistence.testing.models.jpa.metamodel.HardwareDesigner" (id=161) elementDescriptor RelationalDescriptor (id=119) keyField null keyMapping DirectToFieldMapping (id=127) keyMethod null keyName null keyQuery null valueMapping OneToManyMapping (id=117) this MapAttributeImpl<X,K,V> (id=116) elementType EntityTypeImpl<X> (id=120) descriptor RelationalDescriptor (id=119) idAttributes null javaClass Class<T> (org.eclipse.persistence.testing.models.jpa.metamodel.HardwareDesigner) (id=121) members null metamodel MetamodelImpl (id=51) superType MappedSuperclassTypeImpl<X> (id=122) versionAttribute null keyType null managedType EntityTypeImpl<X> (id=46) mapping OneToManyMapping (id=117) >asking for the attributeClass returns null because the attributeField is null - however we have the attributeClassification on the accessor AbstractDirectMapping public Class getMapKeyTargetType(){ return getAttributeAccessor().getAttributeClass(); } >Stacktrace --------------------------- Thread [Thread-3] (Suspended) InstanceVariableAttributeAccessor.getAttributeClass() line: 40 DirectToFieldMapping(AbstractDirectMapping).getMapKeyTargetType() line: 855 DirectToFieldMapping(AbstractDirectMapping).getMapKeyTargetType() line: 1 MapAttributeImpl<X,K,V>.<init>(ManagedTypeImpl<X>, CollectionMapping, boolean) line: 139 EntityTypeImpl<X>(ManagedTypeImpl<X>).initialize() line: 1152 MetamodelImpl.initialize() line: 380 MetamodelImpl.<init>(DatabaseSession) line: 101 MetamodelImpl.<init>(EntityManagerSetupImpl) line: 120 EntityManagerSetupImpl.getMetamodel() line: 1929 EntityManagerSetupImpl.deploy(ClassLoader, Map) line: 383 EntityManagerFactoryImpl.getServerSession() line: 151 EntityManagerFactoryImpl.createEntityManagerImpl(Map) line: 207 EntityManagerFactoryImpl.createEntityManager() line: 195 JUnitTestCase.getServerSession(String) line: 340 JUnitTestCase.getEntityManagerFactory(String, Map) line: 365 JUnitTestCase.getEntityManagerFactory(String) line: 344 EntityManagerFactoryImplTest(MetamodelTest).initialize(boolean) line: 84 EntityManagerFactoryImplTest(MetamodelTest).initialize() line: 65 EntityManagerFactoryImplTest(MetamodelTest).setUp(boolean) line: 54 EntityManagerFactoryImplTest(MetamodelTest).setUp() line: 49 EntityManagerFactoryImplTest.setUp() line: 46 >normal processing example - the referenceClass (instead of the attributeAccessor.attributeField) on the OneToOneMapping is returned as the MapKeyTargetType // UC9: no targetEntity, no MapKey, but generics are set (MapKey has an IdClass with an Embeddable) @OneToMany(cascade=CascadeType.ALL, mappedBy="mappedManufacturerUC9") private Map<Board, Enclosure> enclosureByBoardMapUC9; MapAttributeImpl[org.eclipse.persistence.mappings.OneToManyMapping[enclosureByBoardMapUC9]] this MapAttributeImpl<X,K,V> (id=43) elementType EntityTypeImpl<X> (id=83) descriptor RelationalDescriptor (id=96) idAttributes null javaClass Class<T> (org.eclipse.persistence.testing.models.jpa.metamodel.Enclosure) (id=92) members null metamodel MetamodelImpl (id=56) superType null versionAttribute null keyType null managedType EntityTypeImpl<X> (id=48) mapping OneToManyMapping (id=51) policy MappedKeyMapContainerPolicy (id=55) cloneMethod null constructor Constructor<T> (id=84) containerClass Class<T> (org.eclipse.persistence.indirection.IndirectMap) (id=88) containerClassName null elementClass Class<T> (org.eclipse.persistence.testing.models.jpa.metamodel.Enclosure) (id=92) elementClassName "org.eclipse.persistence.testing.models.jpa.metamodel.Enclosure" (id=94) elementDescriptor RelationalDescriptor (id=96) keyField null keyMapping OneToOneMapping (id=100) keyMethod null keyName null keyQuery null valueMapping OneToManyMapping (id=51) keyMapping OneToOneMapping (id=100) attributeAccessor InstanceVariableAttributeAccessor (id=110) attributeName null cascadeMerge false cascadePersist false cascadeRefresh false cascadeRemove false derivedIdMapping null derivesId false descriptor RelationalDescriptor (id=113) extendPessimisticLockScope ForeignReferenceMapping$ExtendPessimisticLockScope (id=114) fields NonSynchronizedVector (id=117) forceInitializationOfSelectionCriteria false foreignKeyFields NonSynchronizedVector (id=117) hasCustomSelectionQuery false indirectionPolicy NoIndirectionPolicy (id=124) isDefinedAsManyToOneMapping false isForeignKeyRelationship true isJPAId false isLazy null isMapKeyMapping true isOptional true isPrimaryKeyMapping false isPrivateOwned false isReadOnly false isRemotelyInitialized false joinFetch 0 keyTableForMapKey DatabaseTable (id=130) mapsIdValue null mechanism null privateOwnedCriteria null properties null > referenceClass Class<T> (org.eclipse.persistence.testing.models.jpa.metamodel.Board) (id=133) referenceClassName "org.eclipse.persistence.testing.models.jpa.metamodel.Board" (id=135) referenceDescriptor RelationalDescriptor (id=136) relationshipPartner null relationshipPartnerAttributeName null requiresTransientWeavedFields true selectionQuery ReadObjectQuery (id=138) shouldVerifyDelete true sourceToTargetKeyFields HashMap<K,V> (id=145) targetToSourceKeyFields HashMap<K,V> (id=148) tempInitSession null usesBatchReading false weight Integer (id=151) policyKeyType Class<T> (org.eclipse.persistence.testing.models.jpa.metamodel.Board) (id=133) >Summary ------------------------- We go with the workaround in MapAttributeImpl and refactor this out later up into AbstractDirectMapping so we can just return MappedKeyMapContainerPolicy.keyMapping.attributeAccessor.attributeField.
Created attachment 151851 [details] AbstractDirectMapping_.getMapKeyTargetType_fix_for_basic_mapkey_without_name_attribute_in_DI98_UC1a_UC7
>For both of the related DI 98 issues in bug# 294765 and bug# 294811 - part of the context is the fact that the keyMapping only exists on the MappedKeyMapContainerPolicy and not on the other two MapContainerPolicy and DirectMapContainerPolicy because of a constraint on the map key type. ContainerPolicy (A) +=== InterfaceContainerPolicy (A) +=== DirectMapContainerPolicy +=== MapContainerPolicy (use keyField or PK class) +=== MappedKeyMapContainerPolicy (use keyMapping.mapKeyTargetType or attributeClassification)
>This issue is not dependent or blocks bug # 266912 - however when a fix is performed - the workaround in the currently single implementor in MapAttribute should be removed because it will then be redundant.
Created attachment 152167 [details] 294765 check attributeClassification when MapKey annotation missing for basic keyType and remove part of metamodel DI 98 workaround
>See SVN rev# 5793 http://fisheye2.atlassian.com/changelog/eclipselink/?cs=5793 Reviewed by: Guy Pelletier >Model Manufacturer.java @OneToMany(targetEntity=HardwareDesigner.class, cascade=ALL, mappedBy="mappedEmployerUC7") private Map<String, HardwareDesigner> hardwareDesignersMapUC7; HardwareDesigner.java @ManyToOne(fetch=EAGER) private Manufacturer mappedEmployerUC7; JPA Testing: off of rev 5787 (in 2nd clean view) >The existing UC1a and UC7 tests continue to pass with this fix. <testsuite errors="1" failures="0" hostname="xps435" name="org.eclipse.persistence.testing.tests.jpa.FullRegressionTestSuite" tests="1578" time="1409.879" timestamp="2009-11-13T20:09:35"> - this is a know error from another transaction - unrelated
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink