What is referencedColumnName used for in JPA?

只愿长相守 提交于 2019-12-17 07:10:42

问题


In JPA there is an attribute called referencedColumnName that can be set on @JoinColumn, @PrimaryKeyJoinColumn what is the idea behind this setting, can someone give a good example of where this can be used?


回答1:


It is there to specify another column as the default id column of the other table, e.g. consider the following

TableA
  id int identity
  tableb_key varchar


TableB
  id int identity
  key varchar unique

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



回答2:


"referencedColumnName" property is the name of the column in the table that you are making reference with the column you are anotating. Or in a short manner: it's the column referenced in the destination table. Imagine something like this: cars and persons. One person can have many cars but one car belongs only to one person (sorry, I don't like anyone else driving my car).

Table Person
name char(64) primary key
age int

Table Car
car_registration char(32) primary key
car_brand (char 64)
car_model (char64)
owner_name char(64) foreign key references Person(name)

When you implement classes you will have something like

class Person{
   ...
}

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

Hope this helps.




回答3:


Quoting API on referencedColumnName:

The name of the column referenced by this foreign key column.

Default (only applies if single join column is being used): The same name as the primary key column of the referenced table.

Q/A

Where this would be used?

When there is a composite PK in referenced table, then you need to specify column name you are referencing.




回答4:


  • name attribute points to the column containing the asociation, i.e. column name of the foreign key
  • referencedColumnName attribute points to the related column in asociated/referenced entity, i.e. column name of the primary key

You are not required to fill the referencedColumnName if the referenced entity has single column as PK, because there is no doubt what column it references (i.e. the Address single column ID).

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

However if the referenced entity has PK that spans multiple columns the order in which you specify @JoinColumn annotations has significance. It might work without the referencedColumnName specified, but that is just by luck. So you should map it like this:

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

or in case of ManyToMany:

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

Real life example

Two queries generated by Hibernate of the same join table mapping, both without referenced column specified. Only the order of @JoinColumn annotations were changed.

/* 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'

We are querying a join table to get client's emails. The {2, 18} is composite ID of Client. The order of column names is determined by your order of @JoinColumn annotations. The order of both integers is always the same, probably sorted by hibernate and that's why proper alignment with join table columns is required and we can't or should rely on mapping order.

The interesting thing is the order of the integers does not match the order in which they are mapped in the entity - in that case I would expect {18, 2}. So it seems the Hibernate is sorting the column names before it use them in query. If this is true and you would order your @JoinColumn in the same way you would not need referencedColumnName, but I say this only for illustration.

Properly filled referencedColumnName attributes result in exactly same query without the ambiguity, in my case the second query (rev = 2, id_client = 18).




回答5:


For a JPA 2.x example usage for the general case of two tables, with a @OneToMany unidirectional join see https://en.wikibooks.org/wiki/Java_Persistence/OneToMany#Example_of_a_JPA_2.x_unidirectional_OneToMany_relationship_annotations

Screenshot from this WikiBooks JPA article: Example of a JPA 2.x unidirectional OneToMany relationship database



来源:https://stackoverflow.com/questions/11244569/what-is-referencedcolumnname-used-for-in-jpa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!