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

Bug 333100

Summary: References to subclass incorrectly implemented as FK to superclass
Product: z_Archived Reporter: Rich MacDonald <rmacdonald>
Component: EclipselinkAssignee: Project Inbox <eclipselink.orm-inbox>
Status: NEW --- QA Contact:
Severity: normal    
Priority: P2 CC: christopher.delahunt, eclipse, edufrazao, tom.ware, vassilev
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Windows 7   
Whiteboard:
Attachments:
Description Flags
Maven Project replicating the probelm none

Description Rich MacDonald CLA 2010-12-22 10:42:41 EST
Say we have 3 Entity classes, A, B and C:

@Inheritance(strategy=InheritanceType.JOINED)
@Entity class A{}

@Entity class B extends A{}

@Entity class C{
   public B b;
}

Not showing primary keys etc.

The essence is that I am using JOINED inheritance and have a class (C) with an attribute to a specific subclass (B), rather than the superclass (A).

Problem:

Eclipselink does not properly recognize that the reference is to the subclass B. Instead, it treats the reference as pointing to the superclass A. This is seen in two ways:

1) If eclipselink creates the sql tables itself, it specifically creates the FK constraint for C.b on table C that points to the PK on table A. This is incorrect. The FK should point to the PK on table B.

2) When eclipselink persists a new instance of type B and a new instance of type C, table insertion order is table A, then table C, then table B. This is incorrect and will fail on properly specified tables. Insertion order needs to be table A, table B, then table C.

Note that this error also occurs if C.b is defined as @ManyToOne, @Id, etc.
Comment 1 Rich MacDonald CLA 2010-12-22 11:00:00 EST
(Interestingly, eclipselink considers a class named "B" to actually be the byte class. So with different classnames, here is the sql code:)

A -> Superclass_A
B -> Subclass_B
C -> Class_C

CREATE TABLE SUBCLASS_B (ID INTEGER NOT NULL, PRIMARY KEY (ID))
CREATE TABLE SUPERCLASS_A (ID INTEGER NOT NULL, PRIMARY KEY (ID))
CREATE TABLE CLASS_C (ID INTEGER NOT NULL, B_ID INTEGER NULL, PRIMARY KEY (ID))
ALTER TABLE SUBCLASS_B ADD CONSTRAINT FK_SUBCLASS_B_ID FOREIGN KEY (ID) REFERENCES SUPERCLASS_A (ID)
ALTER TABLE CLASS_C ADD CONSTRAINT FK_CLASS_C_B_ID FOREIGN KEY (B_ID) REFERENCES SUPERCLASS_A (ID)

The last line is incorrect. The correct specification is:

ALTER TABLE CLASS_C ADD CONSTRAINT FK_CLASS_C_B_ID FOREIGN KEY (B_ID) REFERENCES SUBCLASS_B (ID)
Comment 2 Tom Ware CLA 2011-01-05 08:55:25 EST
Setting target and priority.  See the following page for the meanings of these fields:

http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines
Comment 3 Chris Delahunt CLA 2012-11-05 15:39:00 EST
I'm not sure this is a bug strictly speaking.  The specification states that the relationship from C->B is to use B's ID.  Because of inheritance, this is defined in A and so uses A's ID.  B's table is treated as a secondary table, so EclipseLink is fine creating constraints the way it does in DDL generation.

If you wish the mapping in C to use the id in tableB instead, try adding a join column specifying the "Subclass_B.ID" field instead of letting it default to "Superclass_A.ID".  This will solve both the constraint generation issue as well as the insert ordering, as it will cause EclipseLink to set the internal hasMultipleTableConstraintDependecy flag to true.  

But specifying a non-PK field in the join column is not really allowed as of JPA 2.0.  So this bug should probably remain open so that setHasMultipleTableConstraintDependecy gets set to true when there is a relationship to a subclass that might span multiple tables.
Comment 4 Eduardo Frazão CLA 2013-09-21 20:42:20 EDT
Hi. I've noted this problem here to.

I Have a little different setup:

SuperClassA

SubClassB extends SuperClassA

AnotherClassC
  - Haves @OneToOne with SubClassB mapped as MapsID

In my project, I've created the database manually, and I get constraint errors because the insert order, because persisting AnotherClassC, the inserts is performed in this order:

 SuperClassA
 AnotherClassC
 SubClassB

It can be Fixed creating a Descriptor Customizer, and setting setHasMultipleTableConstraintDependecy(true)

But if you let eclipselink create the tablets, it will map foreign keys to the root of inheritance.

I will add a small test project on this bug!
Comment 5 Eduardo Frazão CLA 2013-09-21 20:44:51 EDT
Created attachment 235689 [details]
Maven Project replicating the probelm

Tested with Eclipselink 2.4.2
Please note that the Unit test will pass, but note on the logs, the Table DDL, and the Insert Order!

Thanks!
Comment 6 Tom Dunstan CLA 2014-07-08 01:11:40 EDT
We're being bitten by this one too. We don't use DDL generation, but the incorrect insert order is triggering an integrity violation. Even just fixing the insert order would be a big help.
Comment 7 Chris Delahunt CLA 2015-10-26 15:21:57 EDT
*** Bug 480640 has been marked as a duplicate of this bug. ***
Comment 8 Eclipse Webmaster CLA 2022-06-09 10:03:24 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink