【问题标题】:jpa hibernate @OneToOne @JoinColumn referencedColumnName ignoredjpa hibernate @OneToOne @JoinColumn referencedColumnName 被忽略
【发布时间】: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
  • 你找到解决办法了吗?

标签: java hibernate jpa entity


【解决方案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 表示持久化表中的连接列,其中指定了@JoinColumnPerson,(与@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; 

}

【讨论】:

    猜你喜欢
    • 2013-06-22
    • 2020-01-11
    • 2020-08-20
    • 1970-01-01
    • 2020-03-12
    • 2023-03-21
    • 2010-10-07
    • 2013-04-24
    • 2020-01-04
    相关资源
    最近更新 更多