删除多对多条目,同时将两个对象保留在数据库中

时间:2019-02-02 14:20:58

标签: java spring hibernate

我目前在事件和用户之间具有多对多关系。数据库中自动生成的名为event_registrations的表会跟踪关系以及哪个用户根据其ID转到哪个事件。

我想做的是有一个控制器方法,该方法将一个事件ID与一个用户ID列表一起接收,以便将给定的用户从给定的事件中删除。

这是我的模型课:

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

这没有问题,但是条目之后仍然存在于联接表中。进行调试时,确实会从事件对象中删除用户,但更改不会持久保存到数据库中。

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

@Entity
public class Event {

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

}

这里的mappedBy表示User的{​​{1}}列表用于维护这种多对多关系,这意味着Hibernate将更新关系表(eventRegistrations )基于用户的event_registrations列表的内容。您必须采用另一种方法,将其从用户的事件列表中删除:

eventRegistrations

以上代码仅用于显示想法。您可能需要对其进行抛光。

答案 1 :(得分:0)

取决于JPA的实现,您可能必须从所有权方面删除。从WebLogic + TopLink迁移到Spring Boot + Hibernate后,如果我更新了非所有权方的链接,那么多对多链接将无法正确更新。

在您的情况下,您有两个方面:用户是拥有方,而事件是非拥有方(您可以从Event的“ 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();
    }
}