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() {
...
}
How @JoinColumn and @MappedBy works
Actually, seems you're not using @MappedBy
annotation but mappedBy = "department"
in @OneToMany
.
In simple words, mappedBy tells to hibernate
that key of relationship is on the other table (class in this case).
Think on this: usually when you link 2 tables in any DB System, just 1 of those has the foreign key constraint to the other one right?
What MappedBy
allows you to link from the table not containing the constraint to the other table.
About @JoinColumn
it's easier, here you have in table foreign key, so you tell hibernate this is not only a column, but a column that must join a table.
The join column is declared with the
@JoinColumn
annotation which looks like the@Column
annotation. It has one more parameters named referencedColumnName. This parameter declares the column in the targeted entity that will be used to the join. Note that when using referencedColumnName to a non primary key column, the associated class has to be Serializable. Also note that the referencedColumnName to a non primary key column has to be mapped to a property having a single column (other cases might not work).
Find HERE hibernate
mapping documentations.
What harm does using joinColumn instead of mappedBy do?
I was practicing @joincolumn and mappedBy both, and here is what I found when I was analysing hibernate logs.
Performing Save operation using mappedBY
When you create entities using mappedBy, you create the parent object in your child object too, and then perform save operation.
What hibernate does in the back background :-
- Perform insert operation on parent object
- Perform insert operations on child object. Set foreign key reference of parent object at the time
insertion only
Performing Save operation using @JoinColumn
When you create entities using @JoinColumn, you do not create the parent object in your child object.
What hibernate does in the back background :-
- Perform insert operation on parent object
- Perform insert operations on child object
- Perform separate update operations to update foreign key reference on all child object
You can see these operations in your hibernate logs.
Basically @JoinColumn does the same job as mappedBy with extra Update operations.
So, definately performance of mappedBy is better than @JoinColumn.
However, it will not impact if you create one or two entities, but it will definately cause a significance performance issue if we have to create a large amount data.
Used only @mappedBy , no@JoinColumn - join column created in OneToMany relationship, what is then the use of JoinColumn?
Jpa works on the idea of configuration by convention. So, it will perform configuration on your behalf whenever it can. Think of the @Column
annotation, you don't have to apply it on every entity attribute, you would need it only when you have to change something about the attributes.
It's the same with @JoinColumn
, when you added @ManyToOne
, Jpa already knows that you will need the join column and thus was added for you and the default naming convention for the foreign key was applied (attributename_primarykeyoftheothertype
).
Can someone explain mappedBy in JPA and Hibernate?
By specifying the @JoinColumn
on both models you don't have a two way relationship. You have two one way relationships, and a very confusing mapping of it at that. You're telling both models that they "own" the IDAIRLINE column. Really only one of them actually should! The 'normal' thing is to take the @JoinColumn
off of the @OneToMany
side entirely, and instead add mappedBy to the @OneToMany
.
@OneToMany(cascade = CascadeType.ALL, mappedBy="airline")
public Set<AirlineFlight> getAirlineFlights() {
return airlineFlights;
}
That tells Hibernate "Go look over on the bean property named 'airline' on the thing I have a collection of to find the configuration."
Why there is no mappedBy attribute present in @ManyToOne
There are two ways to implement one-to-many relations:
- Using a join table
- Using a foreign key on the many-to-one side
mappedBy
is used for the second way (using a foreign key). You don't have to specify mappedBy
, if you want to use a join table.
Using a join table is not very good idea because you can't control that join table using Hibernate. For example you can't just add a record to a join table directly.
what is @JoinColumn and how it is used in Hibernate
mappedby and JoinColumn issue during hibernate upgrade
As it stated in the JPA specification (see section 2.9 Entity Relationships):
The following rules apply to bidirectional relationships:
- The inverse side of a bidirectional relationship must refer to its owning side by use of the
mappedBy
element of theOneToOne
,OneToMany
, orManyToMany
annotation. ThemappedBy
element designates the property or field in the entity that is the owner of the relationship.- The many side of one-to-many / many-to-one bidirectional relationships must be the owning side, hence the
mappedBy
element cannot be specified on theManyToOne
annotation.- For one-to-one bidirectional relationships, the owning side corresponds to the side that contains the corresponding foreign key.
- For many-to-many bidirectional relationships either side may be the owning side.
The @JoinColumn
annotation can be used on the owning side of unidirectional or bidirectional OneToOne
, ManyToOne
associations OR with unidirectional OneToMany
.
- Bidirectional
@OneToMany
@Entity
@Table(name = "TBL_PARENT")
class Parent {
// We should not use @JoinColumn here, it should be used
// on the the owning side of this association
@OneToMany(mappedBy = "parent")
List<Child> children;
}
@Entity
@Table(name = "TBL_CHILD")
class Child {
@ManyToOne
@JoinColumn(name = "CH_PARENT_ID")
Parent parent;
}
- Unidirectional
OneToMany
(it was added in JPA 2.0):
@Entity
@Table(name = "TBL_PARENT")
class Parent {
// We should not use mappedBy element of the @OneToMany annotation here.
// The name element of the @JoinColumn is referred to the
// TBL_CHILD.CH_PARENT_ID column
@OneToMany
@JoinColumn(name = "CH_PARENT_ID")
List<Child> children;
}
@Entity
@Table(name = "TBL_CHILD")
class Child {
// This part is absent as this is unidirectional OneToMany.
// @ManyToOne
// @JoinColumn(name = "CH_PARENT_ID")
// Parent parent;
}
Related Topics
Standard Concise Way to Copy a File in Java
Do We Have Any Generic Function to Check If Page Has Completely Loaded in Selenium
Difference Between Javac and the Eclipse Compiler
Are Getters and Setters Poor Design? Contradictory Advice Seen
Difference Between a Static Method and a Non-Static Method
How to Hash a Password in Java
When to Use: Java 8+ Interface Default Method, Vs. Abstract Method
How Many Threads Can a Java Vm Support
How to Convert Number to Words in Java
Difference Between Hashmap, Linkedhashmap and Treemap
How to Implement Rest Token-Based Authentication With Jax-Rs and Jersey
How to Get a Platform-Dependent New Line Character
How to Use Wait and Notify in Java Without Illegalmonitorstateexception
How Can a Java Program Get Its Own Process Id