在JPA中使用的referencedColumnName是什么?

时间:2012-06-28 12:23:01

标签: hibernate jpa orm eclipselink openjpa

在JPA中,有一个名为referencedColumnName的属性,可以在@JoinColumn, @PrimaryKeyJoinColumn上设置这个设置背后的想法,有人可以举一个很好的例子来说明这个用途吗?

6 个答案:

答案 0 :(得分:59)

将另一列指定为另一个表的默认 id 列,例如请考虑以下

TableA
  id int identity
  tableb_key varchar


TableB
  id int identity
  key varchar unique

// in class for TableA
@JoinColumn(name="tableb_key", referencedColumnName="key")

答案 1 :(得分:36)

“referencedColumnName”属性是表中要使用要循环的列进行引用的列的名称。或者以简短的方式:它是目标表中引用的列。想象一下这样的事情:汽车和人。一个人可以有很多车,但一辆车只属于一个人(对不起,我不喜欢别人开车)。

  

表人
  name char(64)主键
  age int

     

桌车
  car_registration char(32)主键
  car_brand(char 64)
  car_model(char64)
  owner_name char(64)外键引用 Person(name)

当你实现类时,你会有类似

的东西
class Person{
   ...
}

class Car{
    ...
    @ManyToOne
    @JoinColumn(columnName="owner_name", referencedColumnName="name")
    private Person owner;
}

希望这有帮助。

答案 2 :(得分:19)

引用API on referencedColumnName

  

此外键引用的列的名称   列。

     

默认值(仅在使用单个连接列时适用):   与引用表的主键列相同的名称。

Q / A

  

何时使用?

当引用表中存在复合PK 时,您需要指定要引用的列名。

答案 3 :(得分:7)

  • name属性指向包含asociation的列,即外键的列名
  • referencedColumnName属性指向isociated / referenced实体中的相关列,即主键的列名

如果引用的实体将单列作为PK,则不需要填充referencedColumnName,因为毫无疑问它引用了哪个列(即Address单列ID)。

@ManyToOne
@JoinColumn(name="ADDR_ID")
public Address getAddress() { return address; }

但是,如果引用的实体具有跨越多列的PK,则指定@JoinColumn注释的顺序具有重要性。它可能在没有指定referencedColumnName的情况下工作,但这只是运气。所以你应该像这样映射:

@ManyToOne
@JoinColumns({
    @JoinColumn(name="ADDR_ID", referencedColumnName="ID"),
    @JoinColumn(name="ADDR_ZIP", referencedColumnName="ZIP")
})
public Address getAddress() { return address; }

ManyToMany

@ManyToMany
@JoinTable(
    name="CUST_ADDR",
    joinColumns=
        @JoinColumn(name="CUST_ID"),
    inverseJoinColumns={
        @JoinColumn(name="ADDR_ID", referencedColumnName="ID"),
        @JoinColumn(name="ADDR_ZIP", referencedColumnName="ZIP")
    }
)

现实生活中的例子

Hibernate生成的两个相同连接表映射的查询,两者都没有指定引用列。 仅更改@JoinColumn注释的顺序。

/* load collection Client.emails */ 
select 
emails0_.id_client as id1_18_1_,
emails0_.rev as rev18_1_,
emails0_.id_email as id3_1_,
email1_.id_email as id1_6_0_

from client_email emails0_ 
inner join email email1_ on emails0_.id_email=email1_.id_email 

where emails0_.id_client='2' and 
emails0_.rev='18'
/* load collection Client.emails */ 
select
emails0_.rev as rev18_1_,
emails0_.id_client as id2_18_1_,
emails0_.id_email as id3_1_, 
email1_.id_email as id1_6_0_

from client_email emails0_ 
inner join email email1_ on emails0_.id_email=email1_.id_email 

where emails0_.rev='2' and 
emails0_.id_client='18'

我们正在查询联接表以获取客户的电子邮件。 {2, 18}是客户端的复合ID。列名称的顺序由您@JoinColumn注释的顺序决定。两个整数的顺序总是相同的,可能是通过hibernate排序的,这就是为什么需要与连接表列正确对齐的原因,我们不能或应该依赖映射顺序。

有趣的是整数的顺序与它们在实体中映射的顺序不匹配 - 在这种情况下,我希望{18, 2}。因此,似乎Hibernate在查询中使用它们之前对列名称进行排序。如果这是真的,您可以按照您不需要@JoinColumn的方式订购referencedColumnName,但我这样做只是为了说明。

正确填充的referencedColumnName属性会产生完全相同的查询而不会产生歧义,在我的情况下是第二个查询(rev = 2id_client = 18)。

答案 4 :(得分:0)

对于两个表的一般情况的JPA 2.x示例用法,使用@OneToMany单向连接,请参阅https://en.wikibooks.org/wiki/Java_Persistence/OneToMany#Example_of_a_JPA_2.x_unidirectional_OneToMany_relationship_annotations

此WikiBooks JPA文章的屏幕截图: Example of a JPA 2.x unidirectional OneToMany relationship database

答案 5 :(得分:0)

(可选)此外键引用的列的名称    列。

  • 与案例以外的实体关系映射一起使用时 如此处所述,引用的列在目标表中 实体。
  • 与单向OneToMany外键映射一起使用时, 被引用的列在源实体的表中。
  • 在JoinTable批注中使用时,引用的键列为 在拥有实体的实体表中;如果 连接是反向连接定义的一部分。
  • 在CollectionTable映射中使用时,引用的列位于 包含集合的实体的表。

示例:

Dept
   Long id;
   String deptNo;
   String name;

Employee
  Long id;
  String EmpNo;
  String Name;
  @JoinColumn(name = "dept", referencedColumnName = "deptNo")
  Dept dept;