Java blog about programming – Spring, Hibernate, Scala, QA automation

Main menu

Bidirectional @OneToMany / @ManyToOne association

One of goals the in programming is representation of models from the real world. Very often an application needs to model some relationship between entities. In the last article about Hibernate associations I described the rules of setting up a “one to one” relationship. Today I’m going to show you how to setup a bidirectional “one to many” and “many to one” association. This example will be based on previous Hibernate tutorials.
At the start I need to say that my code example will be based on a simple situation. Let’s imagine a football league. Every league has teams, and in the team can play some players. So the summary is following: one team has many players, one player can play for one team. In this way we get obvious “one to many” and “many to one” relationships.
I use MySQL as a database in this example. Here are scripts for the table’s creation:

Here I specify the column (team_id) which will be joined from the owning side (Teams). Notice that I don’t declare team_id field in the POJO. If I need to change a team for a player I just need to use setTeam(Team team) setter.

That’s it, in this tutorial I have demonstrated how to setup “one to many” and “many to one” bidirectional association. I don’t see any sense in the same tutorial with an example of unidirectional association. Because Hibernate has its own best practices:

Unidirectional associations are more difficult to query. In a large application, almost all associations must be navigable in both directions in queries.

Caused by: org.hibernate.AnnotationException: Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn: com.model.TestNumber.testesult
at org.hibernate.cfg.annotations.CollectionBinder.bind(CollectionBinder.java:526)
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1954)
at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:766)
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:685)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3456)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3410)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1336)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1737)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1788)
at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:247)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:373)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:358)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1547)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1485)

Thank you

my2 koseli

Hi
I figured the problem in this case. I was incorrectly mapping the column name when I should have been mapping the property name.

thank you

Gabriel Andrade

Does this solution works if i want to get players from a selected team with team.getPlayers() method?
Or i necessarily need to have a method with a JPQL to get the players from that team??

George

Hello,
I have one question regarding the above code (main function that creates and persists the entities).

You first create the team and then the players. After you assign the players a team and then assign the players to the team. What I’ve seen by running a similar example, is that whether you add the players to the team before persisting or not does not affect the final state of the database itself, since the filed specifying the team on the player table is set anyway. On the other hand, if you immediately read the entities back and get the list of players from the team you will get an empty list. I guess this has something to do with the 1st level cache Hibernate has.

Am I missing something? Is there a way to avoid having to assign the players to the team, since the team was assigned to the players and that makes no difference to the database?

Thanks again!

http://fruzenshtein.com/ Alex Zvolinskiy

George, you have to set the entities to each other before the final persistence, otherwise you will not achieve desired affect in the database

George

I see! Thanks for responding!

Susi Loma

Why you have to add first the team to the player and additional the set of player to the team?

My preferred solution would be create two players, add them to a list or set, create a team and add the set to the team list. Persist only the team, and all should be fine. The framework should be create the two player and set the correct team id to the players. I tried a lot to get that solution, but i was not able to get the correct result. The team_id is only available if i would add the team direct to the player. Is my prefered solution impossible?