Hibernate OneToMany&ManyToOne

Ryan Zheng
3 min readApr 20, 2020

There are many articles on the internet explaining what JoinColumn and MappedBy do in Hibernate. But I always find it confusing, and I always forget after a while.

I know that if I keep forgetting something that I learned, that means I didn’t really understand it in the first place.

So today I want to explain what uni-directional, bi-directional from a human-understandable way instead of using a bunch of codes that do not explain the essence.

Let’s use Room, Channels as an example. One Room could have many Channels.

So what is really JoinColumn saying?

JoinColumn basically mandates that it is me who is controlling the creation of the foreign key column. Since I am controlling it, of course, I know what the column name of the foreign key is.

However, I didn’t say where to create this column. It all depends on the relationship. (This is important and mostly where the confusion comes). JoinColumn does not say that I am creating the foreign key in my table. It all depends on the relationship types.

For the OneToMany relationship, Hibernate always creates a foreign key on the many sides. This makes sense and also coincides with how the database stores ManyToOne relationships.

In our example, Room is controlling the foreign key creation, Channel does not really know it exists and also it does not know the column name that Room has inserted into it. So it’s uni-directional.

Now I added the Room inside the Channel since we also want to get Room information from Channel.

As I have previously said, JoinColumn is just saying that I am controlling the creation of the foreign key, but I didn’t say where to create the key. It all depends on the setting. Hibernate will always create theforeign key on the Many side of the ManyToOne relationship. This time Channel is the one who is controlling the creation of the foreign key. So it knows what the foreign key column is. But Room has no idea about it.

It’s similar to saying that I give a tag to someone in order to recognize him. He does not know what tag I gave him. So in our case, Room gives a tag to Channel, Channel also gives a tag to Room. Each one of them does not know what tag the other one gives to itself. This is a Uni-directional.

The problem with the above setup is that Hibernate will create two columns representing the same room in the Channel table. One is requested by Room. The other one is requested by Channel. This causes the problem. We only want to create one foreign key column in the Channel table.

So in order to make it bidirectional, We need to make both sides know what tag the other one gives to itself. This is the functionality of mappedBy. mappedBy basically says that the other side already creates a column and its name is mapped by his property. I don’t have to control the creation of the foreign key.

So Room will just check what Channel has done, and use that information to retrieve Channels.

That’s all about OneToMany and ManyToOne. OneToOne is easy to understand. Normally not much confusion.

--

--

Ryan Zheng

I am a software developer who is keen to know how things work