Responses inline...
----- Original Message -----
From: "Emmanuel Bernard" <emmanuel(a)hibernate.org>
To: "Gail Badner" <gbadner(a)redhat.com>
Cc: hibernate-dev(a)lists.jboss.org
Sent: Wednesday, August 24, 2011 4:21:39 PM
Subject: Re: [hibernate-dev] On @OneToOne(optional=true) and @PrimaryKeyJoinColumn
On 24 août 2011, at 23:17, Gail Badner wrote:
> @NotFound is Hibernate-specific, isn't it? Is there anything in the
> JPA 2 spec that covers this functionality?
Nope, JPA 2 does not cover this case.
>
> Since the default for @OneToOne is optional=true, it doesn't seem
> right that it always be implicitly applied with
> @PrimaryKeyJoinColumn, unless optional=false is explicitly
> specified.
>
Oops, I didn't mean: "unless option=false is explicitly specified" above. I
meant: "unless @NotFound(IGNORE) is explicitly specified".
Maybe you're right but I don't have the same rightness feeling.
Anyways, we can't rewrite history and we can differentiate not set
from set to a value in Java's annotations. Besides, I suspect (has to
be verified) that normal forms don't like null values even for foreign
keys. This approach could be considered better though the proper
approach would be to use a join table with unique constraints.
By "normal form" do you mean @OneToOne(optional=true) without a
@PrimaryKeyJoinColumn or derived ID? If so, this case works fine; the foreign key column
is nullable and the foreign key constraint is exported.
> Implicitly applying @NotFound(IGNORE) would break the default
> mappings for unidirectional and bidirectional one-to-one
> relationships documented in the spec.
Can you expand here. I don't follow you.
In 2.10.1 Bidirectional OneToOne Relationships:
The following mapping defaults apply:
Entity A is mapped to a table named A.
Entity B is mapped to a table named B.
Table A contains a foreign key to table B. The foreign key column name is formed as the
con-
catenation of the following: the name of the relationship property or field of entity A;
"_"; the
name of the primary key column in table B. The foreign key column has the same type as
the
primary key of table B and there is a unique key constraint on it.
In 2.10.3.1 Unidirectional OneToOne Relationships:
The following mapping defaults apply:
Entity A is mapped to a table named A.
Entity B is mapped to a table named B.
Table A contains a foreign key to table B. The foreign key column name is formed as the
con-
catenation of the following: the name of the relationship property or field of entity A;
"_"; the
name of the primary key column in table B. The foreign key column has the same type as
the
primary key of table B and there is a unique key constraint on it.
Implicitly applying @NotFound(IGNORE) would mean (I think) that we couldn't export the
foreign key.
>
> It seems reasonable that the application would need to specify
> @NotFound(IGNORE) to get this Hibernate-specific functionality.
There is a big difference. The many to one foreign key column pointing
to a non existent entry is definitely bad form. I am not so sure about
that in the PF/FK case (see above).
>
> Here is my proposal:
>
> @OneToOne(optional=true) with @PrimaryKeyJoinColumn:
>
> A) ID is generated (can only be foreign???)
> 1) @OneToOne is NOT annotated with @NotFound(IGNORE)
> - ignore optional=true and log as INFO
> - export foreign key
> - load using an inner join
ok, log as WARN as the user should fix it.
> 2) @OneToOne is annotated with @NotFound(IGNORE)
> - throw an exception saying that @NotFound(IGNORE) is not
> allowed with generated IDs
>
ok, log as WARN
> B) ID is not generated
> 1) @OneToOne is NOT annotated with @NotFound(IGNORE)
> - ignore optional=true and log as INFO
> - export foreign key
> - load using an inner join
That's where we disagree. I would honor optional=true in this case.
That's not a case that we encounter that often
> 2) @OneToOne is annotated with @NotFound(IGNORE)
> - do not export foreign key
> - load using an outer join
>
ok, log as WARN
> @OneToOne(optional=true) with derived identity
>
> 1) @OneToOne is NOT annotated with @NotFound(IGNORE)
> - ignore optional=true and log as INFO
> - export foreign key
> - load using an inner join
>
ok, log as WARN
> 2) @OneToOne is annotated with @NotFound(IGNORE)
> - throw an exception saying that @NotFound(IGNORE) is not
> allowed with derived IDs
>
ok, log as WARN
> What do you think?
>
> Gail
> ----- Original Message -----
> From: "Emmanuel Bernard" <emmanuel(a)hibernate.org>
> To: hibernate-dev(a)lists.jboss.org
> Sent: Wednesday, August 24, 2011 12:08:33 PM
> Subject: [hibernate-dev] On @OneToOne(optional=true) and
> @PrimaryKeyJoinColumn
>
> There is a distinction between optional=true and @NotFound
>
> I have had a few discussions with Gail on
>
https://hibernate.onjira.com/browse/HHH-4982 and
>
https://hibernate.onjira.com/browse/ANN-725
> Don't spend too much time on these issue reports, they are very
> confusing.
>
> The question boils down to whether or not @OneToOne(optional=true)
> @PrimaryKeyJoinColumn is legal what the implication is on FK
> constraint generation and inner vs outer join use to load the
> object.
>
> Let's take the simple @ManyToOne example
>
> @ManyToOne(optional=true) @JoinColumn(name="profile_fk")
> @NotFound(IGNORE)
> Profile getProfile() { ... };
>
> optional = true means that there may or may not be a Profile ie that
> profile_fk is nullable
> @NotFound(IGNORE) means that if profile_fk points to a profile that
> is not present in the Profile table (say the fk = "emmanuel" and
> there is no profile with "emmanuel" as a PK).
>
> @NotFound(IGNORE) is here to make Hibernate work on *broken*
> databases where the DBA was smart enough to decide FK constraints
> are useless.
>
> This one is easy.
>
> Now for true one to one these two concepts mix in
>
> @Entity
> class User {
> @Id String username;
>
> @OneToOne(optional=true) @PrimaryKeyJoinColumn
> Profile getProfile() { ... };
> }
>
> In this case, a User "emmanuel" has a profile whose primary key is
> "emmanuel": the PK of User is also a foreign key pointing to
> profile.
>
> Now it's perfectly reasonable to imagine that a User has no Profile
> in which case, the User PK which is also the FK to profile would
> point to a non existent entry in Profile. That would mean that we
> cannot enforce the foreign key constraint.
>
> I think that for generated ids (via "foreign" or via derived
> identity), we cannot have optional values. That would defeat the
> purpose of the generator. In these case we should ignore
> optional=true (and log a warning).
>
> For ids that are not generated, I'm torn. I see the use case above
> as a decent use case for which we would not do to outer joins
> instead of inner joins.
> I think that the Hibernate engine reacts properly with the following
> mapping
>
> @Entity
> class User {
> @Id String username;
>
> @OneToOne(optional=true) @PrimaryKeyJoinColumn
> @NotFound(IGNORE)
> Profile getProfile() { ... };
> }
>
> so we could make @NotFound(IGNORE) implicit when
> @OneToOne(optional=true) @PrimaryKeyJoinColumn is found.
>
> Emmanuel
> _______________________________________________
> hibernate-dev mailing list
> hibernate-dev(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/hibernate-dev