Deleting a Many to Many entry while keeping both objects in the database

RDNotorious :

I currently have a Many to Many relationship between Events and Users. The auto generated table in my DB called event_registrations keeps track of the relationship and which user goes to which event based on their ids.

What I want to do is have a controller method that takes in an Event id together with a list of user IDs so that the given users get removed from the given event.

Here are my model classes:

@Entity
public class Event {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  @ManyToMany(mappedBy = "eventRegistrations")
  private List<User> userList;

  public Event() { this.userList = new ArrayList<>(); }

  public Long getId() {
      return id;
  }

  public void setId(Long id) {
      this.id = id;
  }

  public List<User> getUserList() {
      return userList;
  }

  public void registerUser(User user){
      this.userList.add(user);
  }
  public void removeUserRegistration(long userId){
      this.userList.removeIf(user -> user.getId() == userId);
  }
}


@Entity
public class User {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;

@ManyToMany
@JsonIgnore
@JoinTable(
        name = "event_registrations",
        joinColumns = @JoinColumn(name="user_id", referencedColumnName = 
"id"),
        inverseJoinColumns = @JoinColumn(name = "event_id", 
referencedColumnName = "id"))
private List<Event> eventRegistrations;

public Integer getId() {
    return id;
}

public List<Event> getEventRegistrations() {
    return eventRegistrations;
}

public void setEventRegistrations(List<Event> eventRegistrations) {
    this.eventRegistrations = eventRegistrations;
}
}

What I've tried so far in the EventController:

@DeleteMapping(value = "/{id}/registrations", consumes = 
{"application/json"})
public ResponseEntity deleteEventRegistrations(@RequestBody ArrayList<Long> 
data, @PathVariable("id") long id){
    try {
        Event event = eventService.getEventById(id);
        data.forEach(userId -> event.removeUserRegistration(userId));
        return ResponseEntity.ok().build();
    } catch(DataNotFoundException ex){
        return ResponseEntity.notFound().build();
    }
}

This runs without problems but the the entries still exist in the join table afterwards. When debugging this, the users do get deleted from the Event object but the changes don't get persisted to the database.

Any help is appreciated!

Ken Chan :
@Entity
public class Event {

   @ManyToMany(mappedBy = "eventRegistrations")
   private List<User> userList;

}

The mappedBy here means User 's eventRegistrations list are used to maintain this many-to-many relationship , which means Hibernate will update the relationship table (event_registrations) based on the content of User 's eventRegistrations list. You have to do it the other way round which remove that events from an user 's event list :

public void removeUserRegistration(long userId){
     //remove the event from the given user 's event list 
     for(User user : userList){
          if(user.getId().equals(userId)){
               user.getEventRegistrations().removeIf(event->event.getId().equals(this.id));
           }
     }

     //remove given user from the event 's user list 
     //This will not have effects on DB record (as mentioned above) but suggest to also do it for keep the data in java model to be consistency.
     this.userList.removeIf(user -> user.getId() == userId);
 } 

The above codes just for showing the ideas. You may have to polish it.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=160635&siteId=1