jpa hibernate @OneToOne @JoinColumn referencedColumnName 被忽略
Posted
技术标签:
【中文标题】jpa hibernate @OneToOne @JoinColumn referencedColumnName 被忽略【英文标题】:jpa hibernate @OneToOne @JoinColumn referencedColumnName ignored 【发布时间】:2016-08-31 02:01:32 【问题描述】:我在对与另一个具有一对一关系的实体执行 jpql 查询时遇到意外行为。关键是,关系是从根实体的主键到目标实体的一个字段,而不是ID。
示例如下:
// 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;
...
以下jpql查询:
select p from Person p left join fetch p.mainAddress
产生以下 ORACLE SQL 查询:
SELECT ... FROM PERSON p LEFT OUTER JOIN ADDRESS a ON p.PERSON_ID = a.ADDRESS_ID
虽然我期待:
SELECT ... FROM PERSON p LEFT OUTER JOIN ADDRESS a ON p.PERSON_ID = a.PERSON_ID
基本上 referencedColumnName = "PERSON_ID" 属性的属性被忽略,并且在主键上执行连接。
谁能解释一下为什么?
【问题讨论】:
我通过映射反向关系和使用mappedBy属性解决了。这样,ORM 就知道哪个是连接列。谢谢@Alan Hay 你找到解决办法了吗? 【参考方案1】:@OneToOne
按原样映射后,外键将位于 Person 表中,即。 Person 表(如果您没有在 @JoinColumn 注释中指定 person_id)应该有一个 FK 列“address_id”。
形成您期望生成的 SQL 的样子,您似乎希望 FK 在地址表中,即地址有一个 FK 列 person_id。您可以通过以下方式做到这一点:
@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;
【讨论】:
你在句子中说人会address_id
但在示例地址中会有它。
我要说的是:使用@OneToOne 按原样映射,外键将在 Person 表中。注意重点,这是重要的部分。【参考方案2】:
我认为,@OneToOne
映射的@JoinColumn
表示持久化表中的连接列,其中指定了@JoinColumn
:Person
,(与@OneToMany
不同)。
所以使用更简单清晰的映射
@Entity
@Table(name = "persons")
public class Person
@Id
@Column(name = "f_id")
private Long id;
@Column(name = "f_name")
private String name;
@OneToOne(mappedBy = "person", optional = false)
private Address mainAddress;
@Entity
@Table(name = "addreses")
public class Address
@Id
@Column(name = "f_id")
private Long id;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fk_person")
private Person person;
【讨论】:
以上是关于jpa hibernate @OneToOne @JoinColumn referencedColumnName 被忽略的主要内容,如果未能解决你的问题,请参考以下文章
在 Hibernate / JPA 2.1 中延迟加载的 @OneToOne 映射不起作用?
hibernate/jpa double OneToOne 与一个实体的双向关系
jpa hibernate @OneToOne @JoinColumn referencedColumnName 被忽略
如何使用 BooleanBuilder (QueryDSL) 为可选的 OnetoOne JPA/Hibernate 关系建模谓词?