Issue Details (XML | Word | Printable)

Key: GLASSFISH-597
Type: Improvement Improvement
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: tware
Reporter: Sanjeeb Sahoo
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
glassfish

JoinColumns is mandatory for using composite FK

Created: 24/Apr/06 01:11 PM   Updated: 01/Nov/12 10:50 PM   Resolved: 01/Nov/12 10:50 PM
Component/s: entity-persistence
Affects Version/s: 9.0pe
Fix Version/s: 4.0_b60

Time Tracking:
Not Specified

File Attachments: 1. Zip Archive issue_597.zip (3 kB) 24/Apr/06 01:13 PM - Sanjeeb Sahoo

Environment:

Operating System: All
Platform: All


Issuezilla Id: 597
Tags:
Participants: gyorke, marina vatkina, Mitesh Meswani, Sanjeeb Sahoo and tware


 Description  « Hide

It appears to me that TopLink Essential requires JoinColumns to be set when
there is a composite FK. I don't see this being mentioned in the spec. Can the
default join column names not be calculated for such a case? In the attached
test case, the entities are defined like this:

@Entity
@IdClass(EventPK.class)
public class Event implements java.io.Serializable {

@Id String notificationId;

@Id String discriminatorValue = this.getClass().getSimpleName();
}

@Entity
@IdClass(EventPK.class)
public class Alarm implements java.io.Serializable {

@Id String notificationId;

@Id String discriminatorValue = this.getClass().getSimpleName();

@OneToOne Event event;

}

When I run this, I get the exception:
Exception Description: The @JoinColumns on the annotated element [Event
Alarm.event] from the entity class [class Alarm] is incomplete. When the source
entity class uses a composite primary key, a @JoinColumn must be specified for
each join column using the @JoinColumns. Both the name and the
referenceColumnName elements must be specified in each such @JoinColumn.

The same exception appears even when I run verifier.



Sanjeeb Sahoo added a comment - 24/Apr/06 01:13 PM

Created an attachment (id=232)
test case along with README


gyorke added a comment - 24/Apr/06 01:35 PM

In the case of a Class using a Composite PK any references to that class would
default to referencing that PK making any reference a composite FK having
multiple join columns. The specification states, “If there is more than one
join column, a JoinColumn annotation must be specified for each join column
using the JoinColumns annotation. Both the name and the referencedColumnName
elements must be specified in each such JoinColumn annotation.� (Section 9.1.6)

As such, users are required to specify the @JoinColumns annotation or similar XML.


Sanjeeb Sahoo added a comment - 24/Apr/06 01:47 PM

Gordon,

Yes, I have read that section. The spec is not clear, because I don't see such
text in section #2.1.8. Raise it to EG if you think that is more appropriate. If
the spec says the same thing in more than one place, then it needs to
consistent. More over, can you kindly justify why the default JoinColumn names
can not be computed by a provider? For your kind information, Hibernate defaults
the right column names for me. I would like to know the rational for asking user
to supply some value which can be calculated. In one hand, TopLink Essential
automatically adds missing relationship annotations (e.g.) @OneToOne etc (see
GLASSFISH-555), on the other hand it requires user to supply default join column
names! Why?

Thanks,
Sahoo


marina vatkina added a comment - 24/Apr/06 02:44 PM

It really seems an oversight of the spec, because in @JoinTable (9.1.25) both,
joinColumns and inverseJoinColumns are optional, i.e. expect the provider to
figure this out for more than 1 column.

-marina


gyorke added a comment - 25/Apr/06 07:13 AM

Marina,
@JoinColumns is optional in @JoinTable otherwise every usage of @JoinTable
would require @JoinColumns even for a single, defaultable, join column. The
default, in the case of no JoinColumns, clearly states that the default for
@JoinColumn should be used. “The same defaults as for JoinColumn.� (section
9.1.25) which would result in a single JoinColumn being defined. “If no
JoinColumn annotation is specified, a single join column is assumed and the
default values described below apply.� (Section 9.1.6) . As such, the provided
would not be allowed to default to @JoinColumns in this case.

--Gordon


gyorke added a comment - 25/Apr/06 07:14 AM

Sahoo,
You were quite adamant that we not calculate values beyond what is required
by the specification in GLASSFISH-555. Why the change of opinion? The specification
talks about a single join column in section 2.1.8 not a Composite FK. The
specification wording is quite clear in section 9.1.6 with respect to the
requirement of a @JoinColumns annotation. If you are now of the opinion that
TopLink should go beyond the specification and provide extended functionality
then let us mark this bug as an enhancement request.

--Gordon


Sanjeeb Sahoo added a comment - 25/Apr/06 07:40 AM

Gordon,

Can you explain the rational behind mandating use of @JoinColumns? I firmly
believe, it can be computed by a provider and hence should not be mandated. More
over, the two sections in the spec contradict. Issue #555 is different in the
sense that a provider can not always determine the right value. So the spec
requires it to be explicitly specified. Is this the case for @JoinColumns?

Sahoo


gyorke added a comment - 25/Apr/06 08:43 AM

Sahoo,
The reason you considered GLASSFISH-555 a bug is the same reason this issue is
not a bug. TopLink can always default a OneToOne relationship. TopLink can
always default a ToMany relationship where generic collections are used and
GLASSFISH-555 was filed because we chose to do that defaulting. In the case of
@JoinColumns (composite FKs) the provider can only default the @JoinColumn
annotation in its entirety. If a user specifies a partial @JoinColumn, no
referencedColumnName, then the provider can not determine which target column
the custom FK name should reference and what other FK names should be defaulted
and mapped to. The provider can not always calculate defaults for composite FKs.
However, whether the provider can calculate the @JoinColumns or not is a
non-issue. Sections 2.1.8 and 9.1.6 do not contradict each other they
compliment each other. 2.1.8 talks about defaulting a non-composite FK and 9.1.6
talks about how to specify a composite FK making this issue “not a bug�.
TopLink has always highly valued the user experience and I believe that in
the cases where we can calculate @JoinColumns we should. So this issue should
be an enhancement request and GLASSFISH-555 should be marked "invalid"
--Gordon


Sanjeeb Sahoo added a comment - 25/Apr/06 08:51 AM

Gordon,

How can TopLink safely decide whether a relationship is bidirectional? How can
TopLink decide whether a relationship is ManyToMany?

I understand the need to disallow a partial JoinColumns. But when user has not
placed JoinColumns at all, why can't provider calculate the default value? I
like to read the spec in black and white. Where does the spec says that 2.1.8 is
only applicable for non-composite FK.

Sahoo


gyorke added a comment - 25/Apr/06 10:35 AM

Sahoo,
For GLASSFISH-555 TopLink does not need to 'decide' on the nature of a
relationship. TopLink simply defaults undefined relationships as
uni-directional mappings either OneToMany or OneToOne.
As for this bug I do not believe we are in disagreement on if TopLink can
calculate @JoinColumns in certain circumstances only on the nature of this bug
report.
If you are reading the spec in "black and white" where does it mention
composite FKs or multiple join columns(other than the JoinTable reference) in
section 2.1.8?
--Gordon


Sanjeeb Sahoo added a comment - 25/Apr/06 11:49 AM

Section #2.1.8 says the following:
"This section defines the mapping defaults that apply to the use of the
OneToOne, OneToMany,ManyToOne, and ManyToMany relationship modeling annotations."

Where does it say that it is only applicable for entities with simple PK?

Sahoo


Mitesh Meswani added a comment - 01/Nov/12 10:50 PM

Marking as fixed. As per Peter, in EclipseLink, the following example will now work without specifying a JoinColumn:

@Entity

@IdClass(EmpPK.class)
public class Employee implements java.io.Serializable {

@Id String Id1;

@Id String id2;
}

@Entity
public class Address implements java.io.Serializable {
...
...
@OneToOne Employee employee;

}