Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 330628

Summary: @PrimaryKeyJoinColumn(...) is not working equivalently to @JoinColumn(..., insertable = false, updatable = false)
Product: z_Archived Reporter: Karsten Wutzke <kwutzke>
Component: EclipselinkAssignee: Nobody - feel free to take it <nobody>
Status: RESOLVED FIXED QA Contact:
Severity: critical    
Priority: P2 CC: eclipselink.orm-inbox, guy.pelletier, kwutzke, tom.ware
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Windows 7   
Whiteboard:
Attachments:
Description Flags
SSCCE: working example using @JoinColumn
none
SSCCE: non-working example using @PrimaryKeyJoinColumn
guy.pelletier: iplog+
Proposed changes none

Description Karsten Wutzke CLA 2010-11-18 18:58:45 EST
When annotating classes with @JoinColumn(..., insertable = false, updatable = false) validation is working as expected. When annotating with the equivalent @PrimaryKeyJoinColumn, e.g.

@ManyToOne
@PrimaryKeyJoinColumns(value = {@PrimaryKeyJoinColumn(name = "country_code", referencedColumnName = "country_code"), @PrimaryKeyJoinColumn(name = "zip_code", referencedColumnName = "code")})
private Zip zip = null;

... validation fails.

As every child knows (*cough*) @PrimaryKeyJoinColumn(...) is equivalent to @JoinColumn(..., insertable = false, updatable = false). See here:

http://stackoverflow.com/questions/4205628/jpa-is-primarykeyjoincolumn-the-same-as-joincolumn-insertable-u

Stack trace:

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

	at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:420)
	at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl.java:185)
	at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:242)
	at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:230)
	at tld.geoinfo.Main.main(Main.java:28)
Caused by: Exception [EclipseLink-0] (Eclipse Persistence Services - 2.2.0.v20101118-r8514): org.eclipse.persistence.exceptions.IntegrityException
Descriptor Exceptions: 
---------------------------------------------------------

Exception [EclipseLink-48] (Eclipse Persistence Services - 2.2.0.v20101118-r8514): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Multiple writable mappings exist for the field [ZipAreas.state_code].  Only one may be defined as writable, all others must be specified read-only.
Mapping: org.eclipse.persistence.mappings.ManyToOneMapping[city]
Descriptor: RelationalDescriptor(tld.geoinfo.model.ZipArea --> [DatabaseTable(ZipAreas)])

Exception [EclipseLink-48] (Eclipse Persistence Services - 2.2.0.v20101118-r8514): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Multiple writable mappings exist for the field [ZipAreas.country_code].  Only one may be defined as writable, all others must be specified read-only.
Mapping: org.eclipse.persistence.mappings.ManyToOneMapping[city]
Descriptor: RelationalDescriptor(tld.geoinfo.model.ZipArea --> [DatabaseTable(ZipAreas)])

Exception [EclipseLink-48] (Eclipse Persistence Services - 2.2.0.v20101118-r8514): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Multiple writable mappings exist for the field [ZipAreas.country_code].  Only one may be defined as writable, all others must be specified read-only.
Mapping: org.eclipse.persistence.mappings.ManyToOneMapping[zip]
Descriptor: RelationalDescriptor(tld.geoinfo.model.ZipArea --> [DatabaseTable(ZipAreas)])

Exception [EclipseLink-48] (Eclipse Persistence Services - 2.2.0.v20101118-r8514): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Multiple writable mappings exist for the field [Cities.country_code].  Only one may be defined as writable, all others must be specified read-only.
Mapping: org.eclipse.persistence.mappings.ManyToOneMapping[state]
Descriptor: RelationalDescriptor(tld.geoinfo.model.City --> [DatabaseTable(Cities)])

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

	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:667)
	at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.loginAndDetectDatasource(DatabaseSessionImpl.java:615)
	at org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:228)
	at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:392)
	... 4 more

Obviously, @PrimaryKeyJoinColumn is treated to be writable, which is wrong.

I have attached two SSCCE programs using JavaSE, HSQLDB, and Ant. Just drop the current version of EclipseLink into the local lib dir and enter "ant run" in a shell.
Comment 1 Karsten Wutzke CLA 2010-11-18 19:00:01 EST
Created attachment 183442 [details]
SSCCE: working example using @JoinColumn
Comment 2 Karsten Wutzke CLA 2010-11-18 19:00:44 EST
Created attachment 183443 [details]
SSCCE: non-working example using @PrimaryKeyJoinColumn
Comment 3 Karsten Wutzke CLA 2010-11-18 19:18:37 EST
I noticed one strange thing: the only columns that fail have their original columns 2+ tables away named differently *and* in the table directly referenced, the column names must match. All others seem to work (direct references with differing names).

"Original column" = the one at the end of the referenciation path...:

ZipAreas FK1:
ZipAreas.country_code ---) Zips.country_code ---) Countries.iso_code [fail]
ZipAreas.zip_code ---) Zips.code [ok, just one table away and different names]

ZipAreas FK2:
ZipAreas.country_code ---) Cities.country_code ---) States.country_code ---) Countries.iso_code [fail]
ZipAreas.state_code ---) Cities.state_code ---) States.iso_code [fail]
ZipAreas.city_name ---) Cities.name [ok, just one table away and different names]

Cities FK:
Cities.country_code ---) States.country_code ---) Countries.iso_code [fail]
Cities.state_code ---) States.iso_code [ok, just one table away and different names]

... more omitted ...

The ---) are arrows

HTH
Comment 4 Karsten Wutzke CLA 2010-11-18 22:13:16 EST
BTW, you can find a PDF of the data model in the db dir.
Comment 5 Tom Ware CLA 2010-12-09 09:00:17 EST
Setting target and priority.  See the following page for the meanings of these fields:

http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines
Comment 6 Guy Pelletier CLA 2011-01-04 09:50:51 EST
Created attachment 186006 [details]
Proposed changes
Comment 7 Guy Pelletier CLA 2011-01-04 10:26:35 EST
Changes have been submitted.

Reviewed by: Tom Ware

Tests: New test (testPrimaryKeyJoinColumns) added to the DDLGenerationJUnitTestSuite to test model provided by the user. All tests pass (full regression test suite and extended jpa test suite)
Comment 8 Eclipse Webmaster CLA 2022-06-09 10:21:10 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink