Удаление записи «многие ко многим» с сохранением обоих объектов в базе данных - PullRequest
0 голосов
/ 02 февраля 2019

В настоящее время у меня есть отношение «многие ко многим» между событиями и пользователями.Автоматически сгенерированная таблица в моей БД, называемая event_registrations, отслеживает отношения и какие пользователи переходят к какому событию на основе их идентификаторов.

Я хочу создать метод контроллера, который принимает идентификатор события вместе ссписок идентификаторов пользователей, чтобы указанные пользователи были удалены из данного события.

Вот мои классы моделей:

@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;
}
}

Что я пробовал до сих пор в 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();
    }
}

Это работает без проблем, но записи все еще существуют в таблице соединений впоследствии.При отладке этого пользователи удаляются из объекта Event, но изменения не сохраняются в базе данных.

Любая помощь приветствуется!

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

В зависимости от реализации JPA, вам, возможно, придется удалить со стороны владельца.У меня возникли проблемы после перехода с WebLogic + TopLink на Spring Boot + Hibernate, где многие ссылки не были корректно обновлены, если я обновил несобственную сторону.

В вашем случае у вас есть двасторон: пользователь является стороной-владельцем, а событие - стороной, не являющейся владельцем (вы можете увидеть это из «mappedBy» на событии).Это означает, что вы должны удалить из User.eventRegistrations, а не из Event.userList.

Быстрая попытка без каких-либо дополнительных вспомогательных методов:

@DeleteMapping(value = "/{id}/registrations", consumes = 
{"application/json"})
public ResponseEntity<?> deleteEventRegistrations(@RequestBody ArrayList<Long> 
data, @PathVariable("id") long id){
    try {
        Collection<User> users = userService.findUsersByIds(data); // you need to create this
        users.forEach(user -> user.getEventRegistrations().removeIf(event -> event.getId() == id));
        return ResponseEntity.ok().build();
    } catch(DataNotFoundException ex){
        return ResponseEntity.notFound().build();
    }
}
0 голосов
/ 02 февраля 2019
@Entity
public class Event {

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

}

mappedBy здесь означает, что User список eventRegistrations используется для поддержания этого отношения «многие ко многим», что означает, что Hibernate обновит таблицу отношений (event_registrations) на основе содержимогоиз списка eventRegistrations пользователя.Вы должны сделать это наоборот, чтобы удалить эти события из списка событий пользователя:

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);
 } 

Приведенные выше коды только для демонстрации идей.Возможно, вам придется полировать его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...