-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: Typical ManyToMany mapping versus two OneToMany
PostPosted: Tue Jan 05, 2016 7:30 am 
Beginner
Beginner

Joined: Thu Nov 26, 2015 11:40 am
Posts: 33
I have hibernate many-to-many mapping related question and want to understand which one is better.

I have Place and Tag tables that have a many-to-many relationship and Tag_Place table is an association table that stores the relationship between Place and Tag. Table structure is very simple, where in, Place and Tag tables have two columns each i.e., id and name. And Tag_Place table contains iid, place_id and tag_id columns.

Whenever I map these entities in Hibernate I create two entities Place and Tag that have List of each other mapped as ManyToMany. I don't need a separate class to map the association table.

Option:1

Code:
    @Table(name = "place")
    public class Place implements Serializable {
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Id
        private Long id;
        private String name;
       
        @ManyToMany(mappedBy = "places", cascade = {CascadeType.ALL})
        private List<Tag> tags = new ArrayList<>();
    ...
    }


and similarly for Tag class,

Code:
    @Table(name = "tag")
    public class Tag implements Serializable {
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Id
        private Long id;
        private String name;
        @ManyToMany(cascade = {CascadeType.ALL})
        private List<Place> places = new ArrayList<>();
    ... }


I have seen at some places where an entity is created for association table Tag_Place as well and it is mapped as OneToMany in Place and Tag entities as below. And this works too.

Option:2
Code:
    @Table(name = "place")
    public class Place implements Serializable {
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Id
        private Long id;
        private String name;
   
        @OneToMany(mappedBy = "tag", cascade = {CascadeType.ALL})
        private List<TagPlace> tagPlaceList = new ArrayList<>();
    ...}


Tag class

Code:
    @Table(name = "tag")
    public class Tag implements Serializable {
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Id
        private Long id;
        private String name;
        @OneToMany(mappedBy="place", cascade = {CascadeType.ALL})
        private List<TagPlace> tagPlaceList = new ArrayList<>();
    ... }

and finally the `TagPlace` entity for association table

Code:
@Entity
@Table(name = "Tag_Place")
public class TagPlace implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@JoinColumn(name = "tag_id", referencedColumnName = "tag_id")
@ManyToOne
private Tag tag;
@JoinColumn(name = "place_id", referencedColumnName = "place_id")
@ManyToOne
private Player Place
..}


I have always used Option 1 but I would like to get your thoughts on which one is the preferred approach and what is the problem that we might encounter with Option 2?

Also, is there any use case where Option 2 is advisable over Option 1?


Top
 Profile  
 
 Post subject: Re: Typical ManyToMany mapping versus two OneToMany
PostPosted: Tue Jan 05, 2016 4:34 pm 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1638
Location: Romania
That's a great question. The option one might be simpler from a configuration perspective, but it yields less efficient DML statements.

I advise you to use the second option because whenever the associations are controlled by @ManyToOne associations, the DML statements are always the most efficient ones.

The Hibernate 5.0 User Guide that I'm updating, as of writing, contains more details on this topic and examples of the resulting DML statements associated to adding/removing elements.
I hope we can merge my work as soon as possible, but meanwhile here's a preview of how it will look like.

The source code listings are located here.

More, the second approach allows you to define additional properties associated to the junction table (e.g. creation_date, status).

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: Typical ManyToMany mapping versus two OneToMany
PostPosted: Wed Jan 06, 2016 4:54 am 
Beginner
Beginner

Joined: Thu Nov 26, 2015 11:40 am
Posts: 33
Thanks Vlad for your view, that really helped. Will try it out with your code on github.

Just a follow-up question, Which of these options would be lighter on or better, if any, with second level cache in picture?


Top
 Profile  
 
 Post subject: Re: Typical ManyToMany mapping versus two OneToMany
PostPosted: Wed Jan 06, 2016 5:16 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1638
Location: Romania
For caching, if you don't plan to cache the collections, both options are the same.
If you plan on caching the collections too, then the first one will have less overhead since there are only two entities to store instead of three, but only if you measure the impatc you can tell if that's a problem or not.

I'd go for the second approach even for second level caching.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: Typical ManyToMany mapping versus two OneToMany
PostPosted: Wed Jan 06, 2016 12:55 pm 
Beginner
Beginner

Joined: Thu Nov 26, 2015 11:40 am
Posts: 33
Thanks Vlad. I got it.


Top
 Profile  
 
 Post subject: Re: Typical ManyToMany mapping versus two OneToMany
PostPosted: Tue Jan 19, 2016 3:59 pm 
Newbie

Joined: Wed Apr 01, 2009 4:06 pm
Posts: 3
There is another potential advantage of two @ManyToOne mappings to a mapping table. It is very easy to add additional members to the mapping table should the need arise.

Examples:

You have a Sites table, and a Users table. You have a many-to-many relation of sites-users. One user can access many sites. A site can be accessed by many users. Oh, wait! Now we would like to add a logical column to the site-user relation to indicate whether this user is a Site Admin of this site. That flag logically belongs on the site-user combination.

You have a Students table and a Parents table. A Parent can have multiple students. A student can have multiple parents. But later it becomes obvious that you want to add a checkbox (eg, logical) on each Student-Parent mapping for whether this parent receives notification for certain types of events related to this student. Maybe different types of notifications are separate checkboxes. Maybe parent1 gets notified of school events, but parent2 pays the bills.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.