What is the point of @JoinColumn in hibernate?
@JoinColumn indicates that this entity is the owner of the relationship, that the corresponding table has a column with a foreign key to the referenced table.@JoinColumn
annotation is not mandatory. If you will not specify it framework will perform default configuration instead. Hibernate and JPA follows convention over configuration. This means that the developer only needs to specify not standard aspects some custom definitions.
In case of @JoinColumn
, the default column name will be generated like: [field_name]_[id_column_name]
.
In your case:[field_name]
- is person
field of Passport
entity.[id_column_name]
- is @Id
column of related entity. It is id
field of Person
entity.
According to documentation:
2.2.5. Mapping entity associations/relationships
If no @JoinColumn is declared on the owner side, the defaults apply. A
join column(s) will be created in the owner table and its name will be
the concatenation of the name of the relationship in the owner side, _
(underscore), and the name of the primary key column(s) in the owned
side.
So if you need to override the default convention then that's exactly what @JoinColumn
is for.
It covering:
- specify the name of the foreign key column
- specify the name of the column referenced by this foreign key column
- specify column definition
- specify or control the generation of a foreign key definition
- specify the name of the table that contains the column
- whether the property is a unique key
- whether the column is included in SQL UPDATE statements generated by the persistence provider
JPA JoinColumn vs mappedBy
@JoinColumn
could be used on both sides of the relationship. The question was about using @JoinColumn
on the @OneToMany
side (rare case). And the point here is in physical information duplication (column name) along with not optimized SQL query that will produce some additional UPDATE
statements.
According to documentation:
Since many to one are (almost) always the owner side of a bidirectional relationship in the JPA spec, the one to many association is annotated by @OneToMany(mappedBy=...)
@Entity
public class Troop {
@OneToMany(mappedBy="troop")
public Set<Soldier> getSoldiers() {
...
}
@Entity
public class Soldier {
@ManyToOne
@JoinColumn(name="troop_fk")
public Troop getTroop() {
...
}
Troop
has a bidirectional one to many relationship with Soldier
through the troop property. You don't have to (must not) define any physical mapping in the mappedBy
side.
To map a bidirectional one to many, with the one-to-many side as the owning side, you have to remove the mappedBy
element and set the many to one @JoinColumn
as insertable
and updatable
to false. This solution is not optimized and will produce some additional UPDATE
statements.
@Entity
public class Troop {
@OneToMany
@JoinColumn(name="troop_fk") //we need to duplicate the physical information
public Set<Soldier> getSoldiers() {
...
}
@Entity
public class Soldier {
@ManyToOne
@JoinColumn(name="troop_fk", insertable=false, updatable=false)
public Troop getTroop() {
...
}
Is @JoinColumn annotation mandatory in Hibernate?
It is not necessary, JPA follows convention over configuration principle which means there are allways some default values that you can override with annotations.
In case of @JoinColumn
, the default column name is generated like this: <field_name>_<id_column_name>
field_name
is address
in your case, and id_column_name
is referring to the related entity's id, which is id
. Thus, you get address_id
by default.
JPA: difference between @JoinColumn and @PrimaryKeyJoinColumn?
What happens if I promote the column to be a/the PK, too (a.k.a. identifying relationship)? As the column is now the PK, I must tag it with @Id (...).
This enhanced support of derived identifiers is actually part of the new stuff in JPA 2.0 (see the section 2.4.1 Primary Keys Corresponding to Derived Identities in the JPA 2.0 specification), JPA 1.0 doesn't allow Id
on a OneToOne
or ManyToOne
. With JPA 1.0, you'd have to use PrimaryKeyJoinColumn
and also define a Basic
Id
mapping for the foreign key column.
Now the question is: are @Id + @JoinColumn the same as just @PrimaryKeyJoinColumn?
You can obtain a similar result but using an Id
on OneToOne
or ManyToOne
is much simpler and is the preferred way to map derived identifiers with JPA 2.0. PrimaryKeyJoinColumn
might still be used in a JOINED inheritance strategy. Below the relevant section from the JPA 2.0 specification:
11.1.40 PrimaryKeyJoinColumn Annotation
The
PrimaryKeyJoinColumn
annotation
specifies a primary key column that is
used as a foreign key to join to
another table.The
PrimaryKeyJoinColumn
annotation
is used to join the primary table of
an entity subclass in theJOINED
mapping strategy to the primary table
of its superclass; it is used within a
SecondaryTable
annotation to join a
secondary table to a primary table;
and it may be used in aOneToOne
mapping in which the primary key of
the referencing entity is used as a
foreign key to the referenced
entity[108]....
If no
PrimaryKeyJoinColumn
annotation is specified for a subclass
in the JOINED mapping strategy, the
foreign key columns are assumed to
have the same names as the primary key
columns of the primary table of the
superclass....
Example: Customer and ValuedCustomer subclass
@Entity
@Table(name="CUST")
@Inheritance(strategy=JOINED)
@DiscriminatorValue("CUST")
public class Customer { ... }
@Entity
@Table(name="VCUST")
@DiscriminatorValue("VCUST")
@PrimaryKeyJoinColumn(name="CUST_ID")
public class ValuedCustomer extends Customer { ... }
[108] The derived id mechanisms
described in section 2.4.1.1 are now
to be preferred over
PrimaryKeyJoinColumn
for the
OneToOne mapping case.
See also
- Primary Keys through OneToOne Relationships
This source http://weblogs.java.net/blog/felipegaucho/archive/2009/10/24/jpa-join-table-additional-state states that using @ManyToOne and @Id works with JPA 1.x. Who's correct now?
The author is using a pre release JPA 2.0 compliant version of EclipseLink (version 2.0.0-M7 at the time of the article) to write an article about JPA 1.0(!). This article is misleading, the author is using something that is NOT part of JPA 1.0.
For the record, support of Id
on OneToOne
and ManyToOne
has been added in EclipseLink 1.1 (see this message from James Sutherland, EclipseLink comitter and main contributor of the Java Persistence wiki book). But let me insist, this is NOT part of JPA 1.0.
How to use the Hibernate Join Column?
You cannot point to a database column in a mappedBy
.
You have to point to an entity field that is the owning side of the relationship and that is:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "prizv_id")
private Prisvishche abiturients_pr;
So your owned side should be:
@OneToMany(mappedBy = "abiturients_pr")
private List<Abiturient> abiturients = new ArrayList();
Related Topics
How to Have a Textfield Inside a Label
How to Make Image Appear Randomly Every X Seconds in Java Using Timer
Updating Version Numbers of Modules in a Multi-Module Maven Project
Is Null Check Needed Before Calling Instanceof
How to Manage Rest API Versioning with Spring
What Does an Exclamation Mark Mean in Java
Why Converting from Float to Double Changes the Value
Throttling Method Calls to M Requests in N Seconds
A Java API to Generate Java Source Files
Convert Array of Strings into a String in Java
JSONobject:Why JSONobject Changing the Order of Attributes
Validate Jaxbelement in JPA/Jax-Rs Web Service
Different Types of Thread-Safe Sets in Java
Persistence Unit as Resource_Local or Jta
How to Change an Eclipse Default Project into a Java Project
Run .Exe File in Java from File Location
How to Get the File Name from a String Containing the Absolute File Path