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

Java 删除多对多条目,同时在数据库中保留这两个对象,java,spring,hibernate,Java,Spring,Hibernate,我目前在事件和用户之间有一种多对多的关系。my DB中自动生成的名为event_registrations的表根据ID跟踪关系以及哪个用户进入哪个事件 我想做的是有一个控制器方法,它接受一个事件id和一个用户id列表,这样给定的用户就可以从给定的事件中删除 以下是我的模型课程: @Entity public class Event { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Ma

我目前在事件和用户之间有一种多对多的关系。my DB中自动生成的名为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;
}
}
@实体
公开课活动{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私人长id;
@ManyToMany(mappedBy=“eventRegistrations”)
私有列表用户列表;
public Event(){this.userList=new ArrayList();}
公共长getId(){
返回id;
}
公共无效集合id(长id){
this.id=id;
}
公共列表getUserList(){
返回用户列表;
}
公共无效注册表用户(用户){
this.userList.add(用户);
}
public void removeUserRegistration(长用户ID){
this.userList.removeIf(user->user.getId()==userId);
}
}
@实体
公共类用户{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私有整数id;
@许多
@杰索尼奥雷
@可接合(
name=“事件注册”,
joinColumns=@JoinColumn(name=“user\u id”,referencedColumnName=
“身份证”),
inverseJoinColumns=@JoinColumn(name=“event\u id”,
referencedColumnName=“id”))
私人登记;
公共整数getId(){
返回id;
}
公共列表getEventRegistrations(){
返回注册;
}
public void setEventRegistrations(列出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();
    }
}
@DeleteMapping(value=“/{id}/registrations”,使用=
{“应用程序/json”})
public ResponseEntity deleteEventRegistrations(@RequestBody ArrayList
数据,@PathVariable(“id”)长id){
试一试{
Event-Event=eventService.getEventById(id);
data.forEach(userId->event.removeUserRegistration(userId));
返回ResponseEntity.ok().build();
}捕获(DataNotFoundException ex){
返回ResponseEntity.notFound().build();
}
}
这样运行时不会出现问题,但之后连接表中仍然存在条目。调试时,用户确实会从事件对象中删除,但更改不会持久化到数据库中

感谢您的帮助

@Entity
public class Event {

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

}

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

根据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();
    }
}
@DeleteMapping(value=“/{id}/registrations”,使用=
{“应用程序/json”})
public ResponseEntity deleteEventRegistrations(@RequestBody ArrayList
数据,@PathVariable(“id”)长id){
试一试{
Collection users=userService.findUsersByIds(数据);//您需要创建这个
users.forEach(user->user.getEventRegistrations().removeIf(event->event.getId()==id));
返回ResponseEntity.ok().build();
}捕获(DataNotFoundException ex){
返回ResponseEntity.notFound().build();
}
}

你完全正确!它可以工作,但现在删除每个用户后,总是剩下一个用户。你知道为什么会这样吗?我想知道这是否与关系为空有关。很高兴听到这个消息。我已经在回答中解释过了,这是因为“mappedBy”的值定义了在更新
event\u registrations
表中的记录时,我们应该参考java对象中的
event.userList
或User.eventList进行此更新。
@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();
    }
}