我有一个名为direct_message的表,它存储了用户之间的直接消息列表,如下所示:
| ID|父ID|收件人_ID|发送者_ID|标题|消息|发送时间|READ_AT
我想发回一个由SENT_AT排序的最近消息的列表。我使用JPA,所以查询将基于RECIPIENT_ID发送回消息列表,如下所示:
@Repository
@Transactional(readOnly = true)
public interface DirectMessageRepository extends JpaRepository<DirectMessage, Long> {
Page<DirectMessage> findDirectMessageByRecipientId(Long recipientId, Pageable pageable);
}
这是我的Entity类:
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name = "direct_message")
public class DirectMessage {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "direct_message_sequence")
@SequenceGenerator(name = "direct_message_sequence", sequenceName = "direct_message_sequence", allocationSize = 1)
@Column(name = "id", nullable = false)
private Long id;
@ManyToOne
@JoinColumn(name = "parent_id")
private DirectMessage parent;
@ManyToOne
@JoinColumn(nullable = false, name = "sender_id")
private User sender;
@ManyToOne
@JoinColumn(nullable = false, name = "recipient_id")
private User recipient;
private String title;
@Lob
@Column(columnDefinition = "TEXT")
@Size(max = 4000)
private String message;
@Column(name = "sent_at")
private LocalDateTime sentAt;
private Boolean isRead = false;
@Column(name = "read_at")
private LocalDateTime readAt;
@Column(name = "can_reply")
private Boolean canReply;
}
然而,我的问题是,它将发送回一条作为父消息的消息,以及一条包含它作为嵌套父消息的子消息。下面是一个简化的例子(省略了发送者、接收者和其他数据):
[{
"id": 1,
"parent": null,
"recipient": {},
"sender": {},
"title": "Message thread",
"message": "Hello"
}, {
"id": 2,
"parent": {
"id": 1,
"parent": null,
"recipient": {},
"sender": {},
"title": "Message thread",
"message": "Hello"
},
"recipient": {},
"sender": {},
"title": "Message thread",
"message": "This is the reply"
}]
因此,正如您所看到的,父消息(ID 1)是重复的(作为它自己的行,也作为另一条消息的父消息,该消息是该消息的子消息)。在JPA中有没有一种方法可以消除重复数据?并且只在它不是另一个消息线程的一部分时才发送回消息?或者,如果在JPA中不可能,是否有一个SQL查询可以完成这项工作?
1条答案
按热度按时间xkftehaa1#
不要将实体用作DTO!当然,也有一些情况下,这是可以接受的,但只有当你有意识地这样做。我们不要把它放在观测范围内。更有可能的是,你会遇到注解、获取、事务性、数据完整性、数据验证等问题。
1.一个实体对象可以包含多个属性,Map到同一个数据库字段,但只有一个属性是可修改的。因此,根据您的需要,为
parent_id
字段添加另一个。假设您保持parent
不变,您可以添加以下内容:答案中会有家长的代表。
1.创建一个适当的DTO类,其中包含一些需要发送回的属性。让属性名称与实体类中的名称相同(最好但不是强制性的)。不要包含
parent
属性。1.创建服务(类或接口+类),这些方法将把实体转换为
dto
,反之亦然。它可以是简单的逐字段赋值,也可以是ModelMapper的装饰器或其他有用的实现。其主要思想是分离数据的传输和存储。这真的是一个巨大的主题,似乎是数据传输和处理中的一个基本问题,不能用这里的单一答案来涵盖。查看The DTO Pattern和Entity To DTO Conversion for a Spring REST API,或者仅在此处通过关键字进行搜索 * Entity和DTO之间差异 *