Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jpa hibernate @OneToOne @JoinColumn referencedColumnName ignored

I am experiencing an unexpected behavior while performing a jpql query on an entity having a one-to-one relationship with another. The key point is that the relationship is from the primary key of the root entity to a field of the destination entity which is not the ID.

Here is the example:

// root entity
@Entity
@Table(name = "PERSON")

public class Person {

    @Id
    @Column(name = "PERSON_ID")
    private long id;

    private String name;

    @OneToOne(optional = false)
    @JoinColumn(name = "PERSON_ID", referencedColumnName = "PERSON_ID", insertable = false, updatable = false, unique = true)
    private Address mainAddress;
    ...
}
// referenced entity
@Entity
@Table(name = "ADDRESS")
public class Address {

    @Id
    @Column(name = "ADDRESS_ID")
    private long id;

    @Column(name = "PERSON_ID")
    private long personId;
    ...
}

The following jpql query:

select p from Person p left join fetch p.mainAddress

Produces the following ORACLE SQL query:

SELECT ... FROM PERSON p LEFT OUTER JOIN ADDRESS a ON p.PERSON_ID = a.ADDRESS_ID

While I expected :

SELECT ... FROM PERSON p LEFT OUTER JOIN ADDRESS a ON p.PERSON_ID = a.PERSON_ID

Basically the attribute of the referencedColumnName = "PERSON_ID" attribute is ignored and the join is performed on the primary key.

Somebody can please explain me why?

like image 976
leocasucci Avatar asked May 05 '16 10:05

leocasucci


1 Answers

With the @OneToOne mapped as it is, the foreign key is going to be in the Person table, viz. the Person table (if you hadn't specified person_id in the @JoinColumn annotation) should have a FK column 'address_id'.

Form what you expect the generated SQL to look like, it would appear that you want the FK to be in the address table i.e. address has a FK column person_id. You can do this by as follows:

@Entity
@Table(name = "PERSON")

public class Person {

    @Id
    @Column(name = "PERSON_ID")
    private long id;

    private String name;

    @OneToOne(mappedBy = "person")
    private Address mainAddress;

}


@Entity
@Table(name = "ADDRESS")
public class Address {

    @Id
    @Column(name = "ADDRESS_ID")
    private long id;

    @OneToOne(optional = false)
    @JoinColumn(name = "PERSON_ID", insertable = false, updatable = false, unique = true)
    private Person person;

}
like image 153
Alan Hay Avatar answered Oct 22 '22 18:10

Alan Hay