【问题标题】:hibernate many-to-many with additional fields: unable to find entity with id使用附加字段休眠多对多:无法找到具有 id 的实体
【发布时间】:2021-11-05 07:47:55
【问题描述】:

我遇到了一个关于 hibernate jpa n...m 请求的问题。我的设置如下所示:

ChatRoom <--> Participant

需要注意的是映射表 RoomParticipant 有一个额外的活动字段:

Room -> RoomParticipant <- Participant
id      id                 id
name    roomId             name
...     participantId      ...
        active

在完成了一些教程并阅读了很多错误修复建议之后,我坚持使用这个设置(使用 Lombok):

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@EqualsAndHashCode
@Table(name = "rooms")
public class Room {

  @Id
  @GeneratedValue(generator = "uuid")
  @GenericGenerator(name = "uuid", strategy = "uuid")
  private String id;

  @OneToMany(mappedBy = "room")
  private List<RoomParticipant> roomParticipants = new ArrayList<RoomParticipant>();

  public void addParticipant(Participant participant) {
    RoomParticipant roomParticipant = new RoomParticipant(this, participant);
    roomParticipants.add(roomParticipant);
    participant.getRooms().add(roomParticipant);
  }
}

// class annotations omitted
public class Participant {  
  @Id
  private String id;

  @Column
  private String name;

  @OneToMany(mappedBy = "participant", cascade = CascadeType.ALL, orphanRemoval = false)
  @JsonIgnore
  private List<RoomParticipant> rooms = new ArrayList<RoomParticipant>();
}

// class annotations omitted
public class RoomParticipant {
  @EmbeddedId
  @JsonIgnore
  private RoomParticipantPK id;

  @ManyToOne (fetch = FetchType.LAZY)
  @MapsId("roomId")
  @JsonIgnore
  private Room room;

  @ManyToOne (fetch = FetchType.LAZY)
  @MapsId("participantId")
  private Participant participant;

  @Column
  private boolean active;

  public RoomParticipant(Room room, Participant participant) {
    this.room = room;
    this.participant = participant;
    this.id = new RoomParticipantPK(room.getId(), participant.getId());
    this.active = true;
  }
}


@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@Embeddable
public class RoomParticipantPK implements Serializable {
  @Column(name="room_id")
  private String roomId;

  @Column(name="participant_id")
  private String participantId;
}

除了 RoomParticipant 之外,类注解都是一样的。 现在,有了这个我有两个函数调用:一个打开一个新房间,这个工作!

  public Room createRoom(String title, String userId, String username) {
     Participant participant = participantRepository.findById(userId).orElse(createParticipant(userId, username));
     Room room = new Room();
     room.setTitle(title);
     room.addParticipant(participant);
     room.setArchived(false); 
     return chatRoomRepository.save(room);
   }

调用此函数后,新房间已创建,新参与者已创建,room_participant 表已正确填写。

但现在我正在尝试加入具有以下功能的房间:

  public Room joinRoom(String roomId, String sessionId, String username) {
    Participant participant = participantRepository.findById(sessionId).orElse(createParticipant(sessionId, username));
    Room room = chatRoomRepository.findById(roomId).orElseThrow(() -> new InvalidRoomException(roomId));
    room.addParticipant(participant);
    return chatRoomRepository.save(room);
  }

由于以下错误,这不起作用:

javax.persistence.EntityNotFoundException: Unable to find ...chatservice.model.entities.RoomParticipant with id ...chatservice.model.entities.RoomParticipantPK@cc9e297f

这两个函数都调用 createParticipant 这是这样的:

  private Participant createParticipant(String userId, String username) {
     return participantRepository.save(new Participant(userId, username, new  ArrayList<RoomParticipant>()));
   }

存储库是 JpaRepository 的单行扩展

public interface ChatRoomRepository extends JpaRepository<Room, String> {}
public interface ParticipantRepository extends JpaRepository<Participant, String> {}

【问题讨论】:

  • 在您的 RoomParticipantPK 上实现 toString 并查看缺少的 id。
  • 感谢消息现在更加清晰:javax.persistence.EntityNotFoundException: Unable to find com.syncpilot.chatservice.model.entities.RoomParticipant with id 2c9d90817bcaa8db017bcaa9223a0000 P-ID2(发送至http://localhost:8091/chatservice/v1/http/room/2c9d90817bcaa8db017bcaa9223a0000/join 以下正文:displayName: 'name' participantId: 'P-ID2'。在我的数据库中,参与者表中有 P-ID2 的参与者. 另外,房间中确实存在 ID 为 2c9d90817bcaa8db017bcaa9223a0000 的房间。它只是没有在 room_participant 中添加条目
  • 我还系统打印了我的 tostring 中的房间和参与者 ID - 没有丢失,toString 只被调用一次,并且两个 id 都已设置

标签: java database hibernate jpa


【解决方案1】:

您没有保存在 Room.addParticipant 中创建的 RoomParticipant。

为避免实现额外的RoomParticipantRepsitory,只需将Room.roomParticipants 中的注释更改为

 @OneToMany(mappedBy = "room")

 @OneToMany(mappedBy = "room", cascade = CascadeType.ALL, orphanRemoval = true)

【讨论】:

    猜你喜欢
    • 2018-03-18
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 2012-03-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-16
    相关资源
    最近更新 更多