Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 322679 - Conflict between @IdClass and indirection
Summary: Conflict between @IdClass and indirection
Status: CLOSED FIXED
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-08-13 13:37 EDT by Andrei Ilitchev CLA
Modified: 2022-06-09 10:10 EDT (History)
1 user (show)

See Also:


Attachments
Suggested patch (13.97 KB, patch)
2010-08-13 13:53 EDT, Andrei Ilitchev CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Andrei Ilitchev CLA 2010-08-13 13:37:30 EDT
Happens when field name(s) are different in Entity and its IdClass and id is arelation that weaved for indirection.

To reproduce, in org.eclipse.persistence.testing.models.jpa.advanced.PartnerLink entity define both properties as lazy:

@Entity
@Table(name="MW")
@IdClass(org.eclipse.persistence.testing.models.jpa.advanced.PartnerLinkPK.class)
public class PartnerLink {
    private Man man;
    private Woman woman;

	public PartnerLink() {}
	@Id
    @OneToOne(cascade=PERSIST, fetch=LAZY)
	@JoinColumn(name="M")
	public Man getMan() { 
        return man; 
    }
    
    @Id
    @OneToOne(cascade=PERSIST, fetch=LAZY)
	@JoinColumn(name="W")
	public Woman getWoman() { 
        return woman; 
    }
...

Note that in the IdClass uses differently named fields:
public class PartnerLinkPK {
    private int manId;
    private Integer womanId;
...

Result: the persistence unit fails to deploy:
Errors:
TEST SUITE NAME: org.eclipse.persistence.testing.tests.jpa.advanced.EntityManagerJUnitTestSuite
TEST NAME: testSetup(org.eclipse.persistence.testing.tests.jpa.advanced.EntityManagerJUnitTestSuite)
##FAILURE##
RESULT:      FatalError (error)
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.NoSuchMethodException: org.eclipse.persistence.testing.models.jpa.advanced.PartnerLinkPK._persistence_get_woman_vh()
Descriptor: RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.advanced.PartnerLink --> [DatabaseTable(MW)])

Runtime Exceptions: 
---------------------------------------------------------

java.lang.NullPointerException

	at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:408)
	at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl.java:157)
	at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:214)
	at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:202)
	at org.eclipse.persistence.testing.framework.junit.JUnitTestCase.getServerSession(JUnitTestCase.java:373)
	at org.eclipse.persistence.testing.tests.jpa.advanced.EntityManagerJUnitTestSuite.testSetup(EntityManagerJUnitTestSuite.java:359)
	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 junit.framework.TestCase.runTest(TestCase.java:168)
	at junit.framework.TestCase.runBare(TestCase.java:134)
	at org.eclipse.persistence.testing.framework.junit.JUnitTestCase.runBare(JUnitTestCase.java:466)
	at junit.framework.TestResult$1.protect(TestResult.java:110)
	at junit.framework.TestResult.runProtected(TestResult.java:128)
	at junit.framework.TestResult.run(TestResult.java:113)
	at junit.framework.TestCase.run(TestCase.java:124)
	at org.eclipse.persistence.testing.framework.TestExecutor.execute(TestExecutor.java:248)
	at org.eclipse.persistence.testing.framework.TestExecutor.runTest(TestExecutor.java:671)
	at org.eclipse.persistence.testing.framework.ui.SynchronizedTestExecutor.run(SynchronizedTestExecutor.java:61)
Caused by: 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.NoSuchMethodException: org.eclipse.persistence.testing.models.jpa.advanced.PartnerLinkPK._persistence_get_woman_vh()
Descriptor: RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.advanced.PartnerLink --> [DatabaseTable(MW)])

Runtime Exceptions: 
---------------------------------------------------------

java.lang.NullPointerException

	at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:471)
	at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:406)
	at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.postConnectDatasource(DatabaseSessionImpl.java:666)
	at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.login(DatabaseSessionImpl.java:628)
	at org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:230)
	at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:380)
	... 19 more
Comment 1 Andrei Ilitchev CLA 2010-08-13 13:53:02 EDT
Created attachment 176575 [details]
Suggested patch

Eclipselink needs to access the attribute of IdClass corresponding to entity's id attribute: it's required that either attribute names or property names must be the same.

First Eclipselink tries to invoke "woman" field on PartnerLinkPK - that doesn't work in this case. 
Next - in case of property access - it attempts to invoke "getWoman" property accessor on PartnerLinkPK. That should have worked, but LAZY fetch type was weaved into the entity and entity's accessor is no longer the original "getWoman" method, but the new Eclipselink-genarated "_persistence_getWoman_vh".

To fix the problem Eclipselink should keep somewhere the old method name and access here - so the patch adds this info to WeavedBasicIndirectionPolicy.

Changed the test class PartnerLink to use LAZY in both id attributes (to reproduce the problem), also altered getMsanId, getWomanId methods to be @Transient.
Comment 2 Andrei Ilitchev CLA 2010-08-13 15:17:36 EDT
The patch checked into trunk and 2.1.1
Reviewed by Chris.
Comment 3 Michael OBrien CLA 2010-08-23 17:31:53 EDT
>Note: the secondary NPE on missing _vh_ weaved functions is changed to a DescriptorException with suggestions in bug # 323403
Comment 4 Eclipse Webmaster CLA 2022-06-09 10:10:02 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink