简体   繁体   中英

How to correctly delete a many to many relationship in java spring?

I have a many to many relationship between Events and Users. I have made the Event model the owner of the relationship by declaring mappedby() in the User model. I can remove Users from the Event model variable and this works fine when debugging.

Event:

@Entity
public class Event {
  @ManyToMany(fetch = FetchType.LAZY,
        cascade = {
                CascadeType.PERSIST,
                CascadeType.MERGE
        })
  @JoinTable(
        name = "event_registrations",
        joinColumns = @JoinColumn(name="event_id", referencedColumnName = 
        "id"),
        inverseJoinColumns = @JoinColumn(name = "user_id", 
        referencedColumnName = "id"))
  private List<User> userList;
}

public void registerUser(User user){
    this.userList.add(user);
}

public void removeUsers(ArrayList<Integer> userIds){
    for(int userId: userIds){
        this.userList.removeIf(user -> user.getId() == userId);
    }
}

User:

@Entity
public class User {
  @ManyToMany(fetch = FetchType.LAZY,
        cascade = {
                CascadeType.PERSIST,
                CascadeType.MERGE
        },
        mappedBy = "userList")
  @JsonIgnore
  private List<Event> eventRegistrations;

  public void addEventRegistration(Event event) {
    this.eventRegistrations.add(event);
  }

  public void removeEventRegistration(long eventId){
      this.eventRegistrations.removeIf(event -> event.getId() == eventId);
  }
}

The code that executes the removal of users from an event:

Event event = eventService.getEventById(id);
event.removeUsers(userIds);

The only problem I currently have is that these changes don't get saved to the database, even though the userList variable gets updated.

Any help is appreciated!

You need to persist the changes to the DB using SpringData or using the EntityManager . You need to save and flush the changes and it'll trigger the delete actions.

If the change isn't properly persisted in DB, you might need to annotate the delete method with @Transactional from the spring package.

Event event = eventService.getEventById(id);
event.removeUsers(userIds);

eventRepository.saveAndFlush(event);

Also, keep in mind that the lists should be in Sync, in a way that if you remove a user from an event, the event should be removed from the user.

From my experience it's better to use an intermediate table with an ID to persist a many to many relationship. This way you can keep track of attributes like createdAt , updatedAt or createdBy , modifiedBy . The biggest advantage is that then it becomes two one to many relationships from User to UserEvent and from Event to UserEvent and you can create a UserEventRepository and make optimized queries like findByUser(User u) or findByEvent(Event e) .

And, for performance perspective it's better to use Set rather than a List . Hibernate will fire less queries to update. Just get a reeding at Vlad Mihalcea' Blog

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM