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

Gail Badner gbadner at redhat.com
Wed Aug 24 17:17:21 EDT 2011


@NotFound is Hibernate-specific, isn't it? Is there anything in the JPA 2 spec that covers this functionality?

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.  

Implicitly applying @NotFound(IGNORE) would break the default mappings for unidirectional and bidirectional one-to-one relationships documented in the spec.

It seems reasonable that the application would need to specify @NotFound(IGNORE) to get this Hibernate-specific functionality.

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
      2) @OneToOne is annotated with @NotFound(IGNORE)
         - throw an exception saying that @NotFound(IGNORE) is not allowed with generated IDs

   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
      2) @OneToOne is annotated with @NotFound(IGNORE)
         - do not export foreign key
         - load using an outer join

@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

   2) @OneToOne is annotated with @NotFound(IGNORE)
      - throw an exception saying that @NotFound(IGNORE) is not allowed with derived IDs

What do you think?

Gail
----- Original Message -----
From: "Emmanuel Bernard" <emmanuel at hibernate.org>
To: hibernate-dev at 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 at lists.jboss.org
https://lists.jboss.org/mailman/listinfo/hibernate-dev



More information about the hibernate-dev mailing list