[java] Can someone explain mappedBy in JPA and Hibernate?

I am new to hibernate and need to use one-to-many and many-to-one relations. It is a bi-directional relationship in my objects, so that I can traverse from either direction. mappedBy is the recommended way to go about it, however, I couldn't understand it. Can someone explain:

  • what is the recommended way to use it?
  • what purpose does it solve?

For the sake of my example, here are my classes with annotations:

  • Airline OWNS many AirlineFlights
  • Many AirlineFlights belong to ONE Airline

Airline:

@Entity 
@Table(name="Airline")
public class Airline {
    private Integer idAirline;
    private String name;

    private String code;

    private String aliasName;
    private Set<AirlineFlight> airlineFlights = new HashSet<AirlineFlight>(0);

    public Airline(){}

    public Airline(String name, String code, String aliasName, Set<AirlineFlight> flights) {
        setName(name);
        setCode(code);
        setAliasName(aliasName);
        setAirlineFlights(flights);
    }

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="IDAIRLINE", nullable=false)
    public Integer getIdAirline() {
        return idAirline;
    }

    private void setIdAirline(Integer idAirline) {
        this.idAirline = idAirline;
    }

    @Column(name="NAME", nullable=false)
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = DAOUtil.convertToDBString(name);
    }

    @Column(name="CODE", nullable=false, length=3)
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = DAOUtil.convertToDBString(code);
    }

    @Column(name="ALIAS", nullable=true)
    public String getAliasName() {
        return aliasName;
    }
    public void setAliasName(String aliasName) {
        if(aliasName != null)
            this.aliasName = DAOUtil.convertToDBString(aliasName);
    }

    @OneToMany(fetch=FetchType.LAZY, cascade = {CascadeType.ALL})
    @JoinColumn(name="IDAIRLINE")
    public Set<AirlineFlight> getAirlineFlights() {
        return airlineFlights;
    }

    public void setAirlineFlights(Set<AirlineFlight> flights) {
        this.airlineFlights = flights;
    }
}

AirlineFlights:

@Entity
@Table(name="AirlineFlight")
public class AirlineFlight {
    private Integer idAirlineFlight;
    private Airline airline;
    private String flightNumber;

    public AirlineFlight(){}

    public AirlineFlight(Airline airline, String flightNumber) {
        setAirline(airline);
        setFlightNumber(flightNumber);
    }

    @Id
    @GeneratedValue(generator="identity")
    @GenericGenerator(name="identity", strategy="identity")
    @Column(name="IDAIRLINEFLIGHT", nullable=false)
    public Integer getIdAirlineFlight() {
        return idAirlineFlight;
    }
    private void setIdAirlineFlight(Integer idAirlineFlight) {
        this.idAirlineFlight = idAirlineFlight;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="IDAIRLINE", nullable=false)
    public Airline getAirline() {
        return airline;
    }
    public void setAirline(Airline airline) {
        this.airline = airline;
    }

    @Column(name="FLIGHTNUMBER", nullable=false)
    public String getFlightNumber() {
        return flightNumber;
    }
    public void setFlightNumber(String flightNumber) {
        this.flightNumber = DAOUtil.convertToDBString(flightNumber);
    }
}

EDIT:

Database schema:

AirlineFlights has the idAirline as ForeignKey and Airline has no idAirlineFlights. This makes, AirlineFlights as the owner/identifying entity ?

Theoretically, I would like airline to be the owner of airlineFlights.

enter image description here

This question is related to java hibernate jpa jakarta-ee hibernate-mapping

The answer is


Table relationship vs. entity relationship

In a relational database system, a one-to-many table relationship looks as follows:

one-to-many table relationship

Note that the relationship is based on the Foreign Key column (e.g., post_id) in the child table.

So, there is a single source of truth when it comes to managing a one-to-many table relationship.

Now, if you take a bidirectional entity relationship that maps on the one-to-many table relationship we saw previously:

Bidirectional One-To-Many entity association

If you take a look at the diagram above, you can see that there are two ways to manage this relationship.

In the Post entity, you have the comments collection:

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL,
    orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();

And, in the PostComment, the post association is mapped as follows:

@ManyToOne(
    fetch = FetchType.LAZY
)
@JoinColumn(name = "post_id")
private Post post;

Because there are two ways to represent the Foreign Key column, you must define which is the source of truth when it comes to translating the association state change into its equivalent Foreign Key column value modification.

MappedBy

The mappedBy attribute tells that the @ManyToOne side is in charge of managing the Foreign Key column, and the collection is used only to fetch the child entities and to cascade parent entity state changes to children (e.g., removing the parent should also remove the child entities).

Synchronize both sides of a bidirectional association

Now, even if you defined the mappedBy attribute and the child-side @ManyToOne association manages the Foreign Key column, you still need to synchronize both sides of the bidirectional association.

The best way to do that is to add these two utility methods:

public void addComment(PostComment comment) {
    comments.add(comment);
    comment.setPost(this);
}

public void removeComment(PostComment comment) {
    comments.remove(comment);
    comment.setPost(null);
}

The addComment and removeComment methods ensure that both sides are synchronized. So, if we add a child entity, the child entity needs to point to the parent and the parent entity should have the child contained in the child collection.


mappedby="object of entity of same class created in another class”

Note:-Mapped by can be used only in one class because one table must contain foreign key constraint. if mapped by can be applied on both side then it remove foreign key from both table and without foreign key there is no relation b/w two tables.

Note:- it can be use for following annotations:- 1.@OneTone 2.@OneToMany 3.@ManyToMany

Note---It cannot be use for following annotation :- 1.@ManyToOne

In one to one :- Perform at any side of mapping but perform at only one side . It will remove the extra column of foreign key constraint on the table on which class it is applied.

For eg . If we apply mapped by in Employee class on employee object then foreign key from Employee table will be removed.


You started with ManyToOne mapping , then you put OneToMany mapping as well for BiDirectional way. Then at OneToMany side (usually your parent table/class), you have to mention "mappedBy" (mapping is done by and in child table/class), so hibernate will not create EXTRA mapping table in DB (like TableName = parent_child).


mappedby speaks for itself, it tells hibernate not to map this field. it's already mapped by this field [name="field"].
field is in the other entity (name of the variable in the class not the table in the database)..

If you don't do that, hibernate will map this two relation as it's not the same relation

so we need to tell hibernate to do the mapping in one side only and co-ordinate between them.


MappedBy signals hibernate that the key for the relationship is on the other side.

This means that although you link 2 tables together, only 1 of those tables has a foreign key constraint to the other one. MappedBy allows you to still link from the table not containing the constraint to the other table.


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to hibernate

Hibernate Error executing DDL via JDBC Statement How does spring.jpa.hibernate.ddl-auto property exactly work in Spring? Error creating bean with name 'entityManagerFactory' defined in class path resource : Invocation of init method failed JPA Hibernate Persistence exception [PersistenceUnit: default] Unable to build Hibernate SessionFactory Disable all Database related auto configuration in Spring Boot Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] HikariCP - connection is not available Hibernate-sequence doesn't exist How to find distinct rows with field in list using JPA and Spring? Spring Data JPA and Exists query

Examples related to jpa

No converter found capable of converting from type to type How does spring.jpa.hibernate.ddl-auto property exactly work in Spring? Deserialize Java 8 LocalDateTime with JacksonMapper Error creating bean with name 'entityManagerFactory' defined in class path resource : Invocation of init method failed How to beautifully update a JPA entity in Spring Data? JPA Hibernate Persistence exception [PersistenceUnit: default] Unable to build Hibernate SessionFactory How to return a custom object from a Spring Data JPA GROUP BY query How to find distinct rows with field in list using JPA and Spring? What is this spring.jpa.open-in-view=true property in Spring Boot? Spring Data JPA and Exists query

Examples related to jakarta-ee

Java 11 package javax.xml.bind does not exist javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure The type java.io.ObjectInputStream cannot be resolved. It is indirectly referenced from required .class files Deploying Maven project throws java.util.zip.ZipException: invalid LOC header (bad signature) web.xml is missing and <failOnMissingWebXml> is set to true WELD-001408: Unsatisfied dependencies for type Customer with qualifiers @Default Name [jdbc/mydb] is not bound in this Context An internal error occurred during: "Updating Maven Project". java.lang.NullPointerException How to consume a SOAP web service in Java java.lang.ClassNotFoundException: com.sun.jersey.spi.container.servlet.ServletContainer

Examples related to hibernate-mapping

How can I mark a foreign key constraint using Hibernate annotations? Hibernate table not mapped error in HQL query org.hibernate.exception.SQLGrammarException: could not insert [com.sample.Person] Can someone explain mappedBy in JPA and Hibernate? Hibernate - A collection with cascade=”all-delete-orphan” was no longer referenced by the owning entity instance In which case do you use the JPA @JoinTable annotation? How can I map "insert='false' update='false'" on a composite-id key-property which is also used in a one-to-many FK? How to map calculated properties with JPA and Hibernate