Responses inline... ----- Original Message ----- > From: "Emmanuel Bernard" <emman...@hibernate.org> > To: "Gail Badner" <gbad...@redhat.com> > Cc: hibernate-dev@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" <emman...@hibernate.org> > > To: hibernate-dev@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@lists.jboss.org > > https://lists.jboss.org/mailman/listinfo/hibernate-dev _______________________________________________ hibernate-dev mailing list hibernate-dev@lists.jboss.org https://lists.jboss.org/mailman/listinfo/hibernate-dev