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. > 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. > 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. > > 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