Differencebetween Unidirectional and Bidirectional JPA and Hibernate Associations

What is the difference between Unidirectional and Bidirectional JPA and Hibernate associations?

The main differenece is that bidirectional relationship provides navigational access in both directions, so that you can access the other side without explicit queries. Also it allows you to apply cascading options to both directions.

Note that navigational access is not always good, especially for "one-to-very-many" and "many-to-very-many" relationships. Imagine a Group that contains thousands of Users:

  • How would you access them? With so many Users, you usually need to apply some filtering and/or pagination, so that you need to execute a query anyway (unless you use collection filtering, which looks like a hack for me). Some developers may tend to apply filtering in memory in such cases, which is obviously not good for performance. Note that having such a relationship can encourage this kind of developers to use it without considering performance implications.

  • How would you add new Users to the Group? Fortunately, Hibernate looks at the owning side of relationship when persisting it, so you can only set User.group. However, if you want to keep objects in memory consistent, you also need to add User to Group.users. But it would make Hibernate to fetch all elements of Group.users from the database!

So, I can't agree with the recommendation from the Best Practices. You need to design bidirectional relationships carefully, considering use cases (do you need navigational access in both directions?) and possible performance implications.

See also:

  • Deterring “ToMany” Relationships in JPA models
  • Hibernate mapped collections performance problems

JPA associations implementation difference in bidirectional and uni directional

Lets take an example where in one entity A is mapped to many entity B

  1. If you will be fetching data for/querying from entity A and wont ever need to fetch from entity B the going for unidirectional One-to-Many mapping makes sense.
  2. But if you would be querying from entity A as well as from entity B it is recommended to go for bidirectional One-To-Many

why One-To-Many association cannot be Bidirectional and it should just be Unidirectional?

First of all, any relationship can be unidirectional or bidirectional, it's all depend on how you want to display or retrieve your data, and your business rules.

When we can have these two statements, then it is Bidirectional. Then
why she said it can be just Unidirectional?

There is also a big mismatch between the object oriented approach of ORMs like Hibernate and how tables and relationships are defined in a relational database. She can be wright, because, in the point of view of a database, relationships are by default unidirectional.

The difference between unidirectional and bidirectional is defined by the fact that you can access the records of the other side of your relationship from where you are.

What is Bidirectional's exact definition with which she came to such a
conclusion?

In your example we can interpret your relationship like this:

  • Unidirectional: you can get all your addresses from person, but not the inverse

     class Person {

    @OneToMany
    List<Address> addresses;

    }

    class Address {

    // Here you don't add the ManyToOne
    Person p;
    }
  • Bidirectional: you can get all your addresses from person and get a person from an address

     class Person {

    @OneToMany
    List<Address> addresses;
    }

    class Address {

    @ManyToOne
    Person p;
    }

Take a look at those links below:

Difference between unidirectional and bidirectional relational relationship

https://www.baeldung.com/spring-data-rest-relationships

What is Object/Relational mismatch

Pros and cons of JPA bidirectional relationships

Let me try to answer the question with an example:

@Entity
public clas Account {

@OneToMany(mappedBy = "account") // is mappedBy really necessary ?
private List<Advertisements> advertisements;
}

Unidirectional downsides:

Lack of mappedBy atribute leads to unidirectional one-to-many relationship and produces additional join table consisting of foreign keys. This is often treated as JPA pitfall and have negative impact on a performance at a database level (you have three tables instead of two).

@Entity
public clas Advertisements {

@ManyToOne
@JoinColumn(name="ACCOUNT_ID")
private Account account; // is Account really necessary ?
}

Bidirectional downsides:

You can navigate from Advertisements to Account so in terms of JPA you have an access to a single-valued association path "SELECT adv.account FROM Advertisements adv". The assumption is you don't want to therefore one could say this may have a negative impact on a security at JPA level.

best practice using uni/bi assoications in jpa/hibernate

There is no absolute best practice. Use a bidirectional association when you want or need a bidirectional association, and a unidirectional when you want it unidirectional.

Some associations should not be bidirectional. For example, if an address can be an address of a user, or a consumer, or a vendor, or a contact, or whatever, having a reference to each of these entities in the address (all null except one) isn't a wise choice.

Other than that, when two entities are tightly coupled, I generally make the association bidirectional to ease the development and the writing of the queries (as the Hibernate documentation says).

I also agree with the SO answer you linked to: be careful when you have a One to Very Many or Many to Very Many association. But this association, if it's not the owner side, can also stay completely private to the entity (and thus never be loaded), just to help writing queries, but forbidding initializing the very large collection.

To have no problems with JPA, you "just" need to understand and think about what happens under the cover. When developing, turn SQL logging on and look at the queries being executed.

@OneToOne unidirectional and bidirectional

Because you didn't understand how a bidirectional OneToOne is mapped. You don't need two foreign keys. A single one is sufficient to perform a join between both tables, in both directions:

select a.* from address a inner join customer c on c.addressId = a.id;
select c.* from customer c inner join address a on c.addressId = a.id;

The fact that the association is unidirectional or bidirectional doesn't change how the tables are linked together. It just changes the mapping, and allows navigating through the association in both directions.

In a bidirectional association, you always have an owning side (which tells how the association is mapped, using which join column), and an inverse side, where you just say: I'm the other side of the association that is mapped by this field (the field in the mappedBy attribute value) in the target entity.



Related Topics



Leave a reply



Submit