Hibernate OneToOne with common JoinTable does not allow null on non-owning side

Viewed 127

I need to use Hibernate persistence for a Java class with reflexive relationship to itself where the relationship is one-to-one, optional on both sides, recorded in a separate mapping table. I.e:

Code:

@Entity(name = "Clazz")
@Table(name = "clazz")
class Clazz {
    private Integer id;
    private Clazz foo;
    private Clazz bar;
    ...
    @Id
    @Column(name="id", ..., nullable=false)
    @GeneratedValue(...)
    public Integer getId() {return id;}

    @OneToOne(mappedBy = "bar")
    public Clazz getFoo() {return foo;}
    public void setFoo(Clazz foo) {...}

    @OneToOne
    @JoinTable(
        name = "mapping",
        joinColumns = @JoinColumn(name = "foo_id", referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(name = "bar_id", referencedColumnName = "id")
    )
    public Clazz getBar() {return bar;}
    public void setBar(Clazz bar) {...}
    ...
}

DB:

DESC mapping;
Name    Null?     Type
------  --------  -------------
foo_id  NOT NULL  VARCHAR2(256)
bar_id  NOT NULL  VARCHAR2(256)

DESC clazz;
Name    Null?     Type
------  --------  -------------
id      NOT NULL  VARCHAR2(256)

I have existing data populated in the DB and when I try to update one Clazz object as follows:

Clazz c1 = ...; // this object has c1.foo == null
Clazz c2 = ...;
c1.setBar(c2);
c2.setFoo(c1);
...
// Hibernate Session.merge() is called on c1

then I get this exception:

org.hibernate.PropertyValueException: not-null property references a null or transient value: Clazz.foo

I don't understand why a non-null a.foo is required when no such requirement is specified in the Hibernate annotations (OneToOne.optional == true by default). Furthermore, my expectation is that hypothetical setting of a null value there is even valid and should remove a corresponding record from the mapping table.

Could you, please, tell me what I am doing wrong of if this is a bug in Hibernate (v3.x)?

0 Answers
Related