如何使用JPA对实体集合Map进行建模

jqjz2hbq  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(155)

我正在尝试用jpa建模一个收件箱实体...
我的想法是,收件箱是一组消息的Map,Map应从对话的“主题”索引,主题是消息实体的一列,其中包括发送者+接收者名称的连接,始终按字母顺序......这样,对话中的双方将始终指向同一主题

@Table(name = "chat_box")
@Entity(name = "ChatBox")
public class ChatBox {

   @NotNull
   @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, targetEntity = ChatMessage.class)
   @MapKeyColumn(name = "address_type")
   @MapKey(name = "sender")
   private final Map<@NonNull String, @NonNull Set<@NonNull ChatMessage>> messageList = new HashMap<>();
}

@Table(name = "chat_message",
        uniqueConstraints = {@UniqueConstraint(name = "unique_conversation", columnNames = {"conversation"})},
        indexes = {@Index(name = "index_conversation", unique = true, columnList = "conversation")}
)
@Entity(name = "ChatMessage")
public class ChatMessage extends BasicEntity {

   @NotBlank(message = "O campo 'remetente' não pode estar em branco")
   @Size(min = 1, max = 63, message = "O campo 'remetente' deve ter entre ${min} e ${max} carácteres, valor informado; '${validatedValue}'")
   @Column(name = "sender", unique = false, nullable = false, insertable = true, updatable = false, length = 63)
   private String sender;

   @NotBlank(message = "O campo 'destinatario' não pode estar em branco")
   @Size(min = 1, max = 63, message = "O campo 'destinatario' deve ter entre ${min} e ${max} carácteres, valor informado; '${validatedValue}'")
   @Column(name = "receiver", unique = false, nullable = false, insertable = true, updatable = false, length = 63)
   private String receiver;

   @NotBlank(message = "O campo 'mensagem' não pode estar em branco")
   @Size(min = 1, max = 511, message = "O campo 'mensagem' deve ter entre ${min} e ${max} carácteres, valor informado; '${validatedValue}'")
   @Column(name = "message", unique = false, nullable = false, insertable = true, updatable = false, length = 511)
   private String message;

   @Column(name = "_read", unique = true, nullable = false, insertable = true, updatable = true)
   private boolean read;

   @Column(name = "conversation", unique = true, nullable = false, insertable = true, updatable = false, length = 127)
   public String getConversation() {
      return receiver.toLowerCase().compareTo(sender.toLowerCase()) < 1 ? String.format("%s_%s", receiver, sender) : String.format("%s_%s", sender, receiver);
   }

}

我应该如何注解Map属性使其按预期工作??这是一个好方法吗?我应该创建另一个实体,这是一组聊天消息,然后只创建这个实体的Map吗?
感谢所有帮助

njthzxwz

njthzxwz1#

如果你想用两个表来建模,你需要引入一个中间层,比如域模型层,因为JPA不能对Map<?, Collection<?>>建模。

@Entity(name = "ChatBox")
public class ChatBox {

   @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
   @JoinColumn(name = "sender", referencedColumnName = "owner")
   private final Set<@NonNull ChatMessage> messages = new HashSet<>();
}

@Entity(name = "ChatMessage")
public class ChatMessage extends BasicEntity {

   @Column(name = "address_type", unique = false, nullable = false, insertable = true, updatable = false, length = 63)
   private String topic;

   @Column(name = "sender", unique = false, nullable = false, insertable = true, updatable = false, length = 63)
   private String sender;

   @Column(name = "receiver", unique = false, nullable = false, insertable = true, updatable = false, length = 63)
   private String receiver;

   @Column(name = "message", unique = false, nullable = false, insertable = true, updatable = false, length = 511)
   private String message;

   @Column(name = "_read", unique = true, nullable = false, insertable = true, updatable = true)
   private boolean read;

}

我认为这是一个完美的Blaze-Persistence实体视图用例。
我创建这个库是为了允许在JPA模型和自定义接口或抽象类定义的模型之间进行简单的Map,就像Spring Data Projections一样。其思想是您可以按照自己喜欢的方式定义目标结构(域模型),并通过JPQL表达式将属性(getter)Map到实体模型。
使用Blaze-Persistence Entity-Views时,您的用例的DTO模型可能如下所示:

@EntityView(ChatBox.class)
public interface ChatBoxDto {
    @IdMapping
    Long getId();
    @MappingIndex("topic")
    Map<String, Set<ChatMessageDto>> getMessages();

    @EntityView(ChatMessage.class)
    interface ChatMessageDto {
        @IdMapping
        Long getId();
        String getSender();
        String getReceiver();
        String getMessage();
        boolean isRead();
    }
}

查询是将实体视图应用于查询的问题,最简单的是按id查询。
ChatBoxDto a = entityViewManager.find(entityManager, ChatBoxDto.class, id);
Spring Data 集成允许您像Spring Data 投影一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

Page<ChatBoxDto> findAll(Pageable pageable);

最好的部分是,它只会获取实际需要的状态!

相关问题