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."
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() {
...
}
Understanding mappedBy annotation in Hibernate
That's normal.
With the mappedBy
, you directly tell Hibernate/JPA that one table owns the relationship, and therefore it is stored as a column of that table.
Without, the relationship is external and Hibernate/JPA need to create another table to store the relationship.
Example:
- A stackoverflow
Question
have severalAnswer
. - An
Answer
is owned by one and only oneQuestion
.
In plain JDBC, you would create two table:
Questions(Question_ID, ...);
Answers(Answer_ID, Question_ID, ...);
Where Question_ID
is foreign key referencing Question.Question_ID
.
As for the other case, I don't have a real case since there are almost every time many to many with a unique constraint (eg: a Question
may have several Answer
, and Answer
may have physically have several Question
, but appears only once for any Question
).
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;
}
Why do I need to use mappedBy Annotation?
Why do you need to use "mappedBy" ? You use it for defining that a relation is BIDIRECTIONAL and specifying what is the other side of the relation (for 1-1 you specify it at the side with the FK, and for 1-N you specify it at the Collection side). So you DON'T "HAVE TO" specify it if your relation is UNIDIRECTIONAL. Reading any half decent JPA docs would tell you that; aren't the docs for your implementation telling you this?
Hibernate: Specifying correct value for mappedBy attribute for composite PK, FK
It should be like this:
@OneToOne(mappedBy="veh")
private UserInfo userInfo;
The mappedBy
element identifies the inverse side of a relationship. here you have relation between Vehicle and UserInfo so to identify inverse side of relation should using it by other side property. here veh
.
for more information see this
Related Topics
Why Is "Extends T" Allowed But Not "Implements T"
Java Byte Array to String to Byte Array
Java Simpledateformat("Yyyy-Mm-Dd'T'Hh:Mm:Ss'Z'") Gives Timezone as Ist
How to Restart a Java Application
Converting Symbols, Accent Letters to English Alphabet
Using Heapdumponoutofmemoryerror Parameter for Heap Dump for Jboss
How to Get Java 11 Run-Time Environment Working Since There Is No More Jre 11 for Download
Call an Executable and Pass Parameters
Controlling Maven Final Name of Jar Artifact
Bounding Generics with 'Super' Keyword
What Is the Java's Internal Represention for String? Modified Utf-8? Utf-16
How to Achieve Method Chaining in Java
Getting the Text That Follows After the Regex Match
Importing Two Classes with Same Name. How to Handle
How to Get Frequency from Fft Result
How to Get a Unique Computer Identifier in Java (Like Disk Id or Motherboard Id)