JPA查询向用户返回最新的直接消息时出现问题,其中每条消息都可能有一个父消息

h7wcgrx3  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(135)

我有一个名为direct_message的表,它存储了用户之间的直接消息列表,如下所示:
| ID|父ID|收件人_ID|发送者_ID|标题|消息|发送时间|READ_AT
我想发回一个由SENT_AT排序的最近消息的列表。我使用JPA,所以查询将基于RECIPIENT_ID发送回消息列表,如下所示:

  1. @Repository
  2. @Transactional(readOnly = true)
  3. public interface DirectMessageRepository extends JpaRepository<DirectMessage, Long> {
  4. Page<DirectMessage> findDirectMessageByRecipientId(Long recipientId, Pageable pageable);
  5. }

这是我的Entity类:

  1. @Getter
  2. @Setter
  3. @NoArgsConstructor
  4. @Entity
  5. @Table(name = "direct_message")
  6. public class DirectMessage {
  7. @Id
  8. @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "direct_message_sequence")
  9. @SequenceGenerator(name = "direct_message_sequence", sequenceName = "direct_message_sequence", allocationSize = 1)
  10. @Column(name = "id", nullable = false)
  11. private Long id;
  12. @ManyToOne
  13. @JoinColumn(name = "parent_id")
  14. private DirectMessage parent;
  15. @ManyToOne
  16. @JoinColumn(nullable = false, name = "sender_id")
  17. private User sender;
  18. @ManyToOne
  19. @JoinColumn(nullable = false, name = "recipient_id")
  20. private User recipient;
  21. private String title;
  22. @Lob
  23. @Column(columnDefinition = "TEXT")
  24. @Size(max = 4000)
  25. private String message;
  26. @Column(name = "sent_at")
  27. private LocalDateTime sentAt;
  28. private Boolean isRead = false;
  29. @Column(name = "read_at")
  30. private LocalDateTime readAt;
  31. @Column(name = "can_reply")
  32. private Boolean canReply;
  33. }

然而,我的问题是,它将发送回一条作为父消息的消息,以及一条包含它作为嵌套父消息的子消息。下面是一个简化的例子(省略了发送者、接收者和其他数据):

  1. [{
  2. "id": 1,
  3. "parent": null,
  4. "recipient": {},
  5. "sender": {},
  6. "title": "Message thread",
  7. "message": "Hello"
  8. }, {
  9. "id": 2,
  10. "parent": {
  11. "id": 1,
  12. "parent": null,
  13. "recipient": {},
  14. "sender": {},
  15. "title": "Message thread",
  16. "message": "Hello"
  17. },
  18. "recipient": {},
  19. "sender": {},
  20. "title": "Message thread",
  21. "message": "This is the reply"
  22. }]

因此,正如您所看到的,父消息(ID 1)是重复的(作为它自己的行,也作为另一条消息的父消息,该消息是该消息的子消息)。在JPA中有没有一种方法可以消除重复数据?并且只在它不是另一个消息线程的一部分时才发送回消息?或者,如果在JPA中不可能,是否有一个SQL查询可以完成这项工作?

xkftehaa

xkftehaa1#

不要将实体用作DTO!当然,也有一些情况下,这是可以接受的,但只有当你有意识地这样做。我们不要把它放在观测范围内。更有可能的是,你会遇到注解、获取、事务性、数据完整性、数据验证等问题。
1.一个实体对象可以包含多个属性,Map到同一个数据库字段,但只有一个属性是可修改的。因此,根据您的需要,为parent_id字段添加另一个。假设您保持parent不变,您可以添加以下内容:

  1. @Column(name = 'parent_id', insertable = false, updatable = false)
  2. private Long parentId;

答案中会有家长的代表。
1.创建一个适当的DTO类,其中包含一些需要发送回的属性。让属性名称与实体类中的名称相同(最好但不是强制性的)。不要包含parent属性。
1.创建服务(类或接口+类),这些方法将把实体转换为dto,反之亦然。它可以是简单的逐字段赋值,也可以是ModelMapper的装饰器或其他有用的实现。其主要思想是分离数据的传输和存储。
这真的是一个巨大的主题,似乎是数据传输和处理中的一个基本问题,不能用这里的单一答案来涵盖。查看The DTO PatternEntity To DTO Conversion for a Spring REST API,或者仅在此处通过关键字进行搜索 * Entity和DTO之间差异 *

相关问题