This Bugzilla instance is deprecated, and most Eclipse projects now use GitHub or Eclipse GitLab. Please see the deprecation plan for details.
Bug 294765 - JPA 2.0: MapKey keyType DirectToField processing should return attributeClassification class in getMapKeyTargetType when accessor.attributeField is null
Summary: JPA 2.0: MapKey keyType DirectToField processing should return attributeClass...
Status: RESOLVED FIXED
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows NT
: P2 normal (vote)
Target Milestone: ---   Edit
Assignee: Nobody - feel free to take it CLA
QA Contact:
URL: http://wiki.eclipse.org/EclipseLink/D...
Whiteboard:
Keywords:
Depends on: 266912
Blocks: 294254 303063
  Show dependency tree
 
Reported: 2009-11-10 12:08 EST by Michael OBrien CLA
Modified: 2022-06-09 10:32 EDT (History)
3 users (show)

See Also:


Attachments
AbstractDirectMapping_.getMapKeyTargetType_fix_for_basic_mapkey_without_name_attribute_in_DI98_UC1a_UC7 (813 bytes, patch)
2009-11-10 12:10 EST, Michael OBrien CLA
no flags Details | Diff
294765 check attributeClassification when MapKey annotation missing for basic keyType and remove part of metamodel DI 98 workaround (4.38 KB, patch)
2009-11-13 10:36 EST, Michael OBrien CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Michael OBrien CLA 2009-11-10 12:08:41 EST
>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.
Comment 1 Michael OBrien CLA 2009-11-10 12:10:09 EST
Created attachment 151851 [details]
AbstractDirectMapping_.getMapKeyTargetType_fix_for_basic_mapkey_without_name_attribute_in_DI98_UC1a_UC7
Comment 2 Michael OBrien CLA 2009-11-10 16:09:56 EST
>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)
Comment 3 Michael OBrien CLA 2009-11-12 07:42:59 EST
>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.
Comment 4 Michael OBrien CLA 2009-11-13 10:36:20 EST
Created attachment 152167 [details]
294765 check attributeClassification when MapKey annotation missing for basic keyType and remove part of metamodel DI 98 workaround
Comment 5 Michael OBrien CLA 2009-11-13 16:43:30 EST
>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
Comment 6 Eclipse Webmaster CLA 2022-06-09 10:32:33 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink