Jpa Joincolumn VS Mappedby

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 :-

  1. Perform insert operation on parent object
  2. 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 :-

  1. Perform insert operation on parent object
  2. Perform insert operations on child object
  3. 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:

  1. Using a join table
  2. 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 the OneToOne, OneToMany, or ManyToMany annotation. The mappedBy 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 the ManyToOne 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.

  1. 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;
}

  1. 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



Leave a reply



Submit