@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" <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

Reply via email to