在JPA中使用的referencedColumnName是什么?

ams*_*ams 65 orm hibernate jpa openjpa eclipselink

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

Fir*_*iro 65

它是指定另一列作为另一个表的默认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")
Run Code Online (Sandbox Code Playgroud)


EAm*_*mez 42

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

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

表格car
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;
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.


JMe*_*nik 21

在referencedColumnName上引用API:

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

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

Q/A

这会用到哪里?

如果引用表中存在复合PK,则需要指定要引用的列名.

  • 或者,当你有一个中间表时,在`@ ManyToMany`映射中. (3认同)

Vla*_*čík 8

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

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

@ManyToOne
@JoinColumn(name="ADDR_ID")
public Address getAddress() { return address; }
Run Code Online (Sandbox Code Playgroud)

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

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

或者在以下情况下ManyToMany:

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

真实的例子

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'
Run Code Online (Sandbox Code Playgroud)
/* 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'
Run Code Online (Sandbox Code Playgroud)

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

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

正确填充的referencedColumnName属性导致完全相同的查询而没有歧义,在我的情况下是第二个查询(rev = 2,id_client = 18).