JPA中所使用的referencedColumnName是什么?


73

在JPA中,有一个名为的属性referencedColumnName,可以根据该设置的@JoinColumn, @PrimaryKeyJoinColumn含义设置该属性,有人可以举例说明可以在何处使用它吗?

Answers:


72

在那里可以将另一列指定为另一张表的默认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")

48

“ referencedColumnName”属性是您要注释的表中正在引用的表中的列的名称。或简而言之:这是目标表中引用的列。想象一下这样的事情:汽车和人。一个人可以拥有许多汽车,但一辆汽车仅属于一个人(对不起,我不喜欢其他人驾驶我的汽车)。

表人员
名称char(64)主键
年龄int

表Car
car_registration char(32)主键
car_brand(字符64)
car_model(char64)
owner_name char(64)外键引用Person(name)

当您实现类时,您将获得类似

class Person{
   ...
}

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

编辑:正如@ searchengine27所评论的那样,columnName在Java7文档的持久性部分中作为字段不存在。我不记得从何处获取此属性,但是我记得使用它,这就是为什么我将其留在示例中的原因。


明确的答案。哈利路亚。
granadaCoder

eh ...columnName不是注释的字段...
searchengine27

@ searchengine27,这个答案来自7年前...根据文档,它似乎columnName未在java7规范或java6中定义(这是我在回答此问题时所使用的版本)。这样看来您是对的
EAmez

而且,只有极少数的例外,Java(和JavaEE)向后兼容。相对于删除,通常不赞成使用东西。因此,我通常不会直接跳转到“已删除”。甚至JavaSE中的泛型都是在Java SE 5中发布的,这样做的初衷是向后兼容,这使对类型擦除一无所知的每个人都感到沮丧和困惑。
searchengine27

21

在referencedColumnName上引用API

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

缺省值(仅在使用单个连接列的情况下适用):与引用表的主键列相同的名称。

问/答

将在哪里使用?

如果被引用的表中有一个复合PK,那么您需要指定要引用的列名。


3
或者,在@ManyToMany映射中有中间表时。
WesternGun

9
  • name 属性指向包含关联的列,即外键的列名
  • referencedColumnName 属性指向关联/引用实体中的相关列,即主键的列名

referencedColumnName如果所引用的实体具有单个列作为PK,则不需要填写,因为毫无疑问,它引用的是哪个列(即,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注释的顺序确定。两个整数的顺序总是相同的,可能是按休眠方式排序的,这就是为什么需要与联接表列正确对齐的原因,而我们不能也不应该依赖映射顺序。

有趣的是,整数的顺序与在实体中映射整数的顺序不匹配-在这种情况下,我希望如此{18, 2}。因此,Hibernate似乎正在对列名称进行排序,然后才在查询中使用它们。如果是这样,您将以@JoinColumn不需要的方式订购referencedColumnName,但我仅出于说明目的而说。

正确填写referencedColumnName属性导致无歧义完全相同的查询,在我的情况下,第二个查询(rev = 2id_client = 18)。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.