[hibernate-dev] On @OneToOne(optional=true) and @PrimaryKeyJoinColumn

Emmanuel Bernard emmanuel at hibernate.org
Wed Aug 24 15:08:33 EDT 2011


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



More information about the hibernate-dev mailing list