What is referencedColumnName used for in JPA?
Asked Answered
B

5

99

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?

Bitthia answered 28/6, 2012 at 12:23 Comment(0)
S
91

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")
Stringent answered 28/6, 2012 at 14:9 Comment(0)
M
55

"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([column]name="owner_name", referencedColumnName="name")
    private Person owner;
}

EDIT: as @searchengine27 has commented, columnName does not exist as a field in persistence section of Java7 docs. I can't remember where I took this property from, but I remember using it, that's why I'm leaving it in my example.

Monody answered 4/7, 2012 at 11:58 Comment(5)
eh...columnName is not a field of the annotation...Grandmamma
@searchengine27, this answer is from more than 7 years ago... as per documentation it looks like columnName is not defnined in java7 spec nor java6 (this was the version I was using when answered this). So it looks like you're rightMonody
Also, with only quite a few minimal exceptions, Java (and JavaEE) are quite backwards compatible. Things are typically deprecated in favor over removal. So I wouldn't jump straight to 'it was removed' typically. Even generics in JavaSE were released in Java SE 5, and done so with backwards compatibility in mind, at the pure frustration and bewilderment of everyone who knows anything about type erasure.Grandmamma
Any example for OneToMany in parent table that has the JoinColumn annotation?Hyalite
Sorry @Hyalite but I haven't used Java for almost 10 years and can't remember anything JPA related.Monody
C
25

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.

Clomp answered 28/6, 2012 at 13:32 Comment(1)
Or, in @ManyToMany mapping when you have a middle table.Feather
F
20
  • 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).

Flaherty answered 22/9, 2015 at 12:2 Comment(0)
H
2

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

Hectocotylus answered 31/8, 2017 at 14:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.