Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding an entity into an large Many-To-Many relationship in JPA

I have a Group entity that has a list of User entities in a many to many relationship. It is mapped by a typical join table containing the two IDs. This list may be very large, a million or more users in a group.

I need to add a new user to the group, typically that will be something like

group.getUsers().add(user);
user.getGroups().add(group);

em.merge(group);
em.merge(user);

If I understand typical JPA operation, will this require pulling down the entire list of 1 million+ users into the collection in order to add the new user and then save? That doesn't sound very scalable to me.

Should I simply not be defining this relationship in JPA? Should I be manipulating the join table entries directly in a case like this?

Please forgive the loose syntax, I'm actually using Spring Data JPA so I don't directly use the entity manager directly very often, but the question seems to be general to JPA so I wanted to pose it that way.

like image 321
nfdavenport Avatar asked Sep 20 '13 05:09

nfdavenport


1 Answers

Design your models like this and play with UserGroup for associations.

@Entity
public class User {

   @OneToMany(cascade = CascadeType.ALL, mappedBy = "user",fetch = FetchType.LAZY)
    @OnDelete(action = OnDeleteAction.CASCADE)
    private Set<UserGroup> userGroups = new HashSet<UserGroup>();

}


@Entity
@Table(name="user_group", 
    uniqueConstraints = {@UniqueConstraint(columnNames = {"user_id", "group_id"})})
public class UserGroup {


    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id", nullable = false)
    @ForeignKey(name = "usergroup_user_fkey")
    private User user;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "group_id", nullable = false)
    @ForeignKey(name = "usergroup_group_fkey")  
    private Group group;

}


@Entity
public class Group {

    @OneToMany(cascade = CascadeType.ALL, mappedBy="group", fetch = FetchType.LAZY )
    @OnDelete(action = OnDeleteAction.CASCADE)      
    private Set<UserGroup>  userGroups  = new HashSet<UserGroup>();

}

Do like this.

     User user =     findUserId(id); //All groups wont be loaded they are marked lazy
     Group group =  findGroupId(id);  //All users wont be loaded they are marked lazy

     UserGroup  userGroup = new UserGroup();
     userGroup.setUser(user);
     userGroup.setGroup(group);

     em.save(userGroup);
like image 86
Prabhakaran Ramaswamy Avatar answered Oct 15 '22 23:10

Prabhakaran Ramaswamy