英文:
How make a polymorphic query with Hibernate JoinFormula Annotation?
问题
I try to find the best way to implement a calculated property witch query the latest message into the chat entity.
尝试找到实现计算属性以查询聊天实体中的最新消息的最佳方法。
The Message entity is implemented as a class hierarchy according to the type of the message (Image, Text, Url ...)
消息实体根据消息类型(图像、文本、URL 等)实现为类层次结构。
@Entity
@Table(name = MessageEntity.TABLE_NAME)
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "Type", discriminatorType = DiscriminatorType.STRING)
@NamedEntityGraphs({
@NamedEntityGraph(name = MessageEntity.GRAPH_MESSAGES_FULL, attributeNodes = {
@NamedAttributeNode(value = "creator", subgraph = UserEntity.GRAPH_USER_BASIC),
@NamedAttributeNode(value = "chat")
})
})
@Getter
@Setter
public abstract class MessageEntity extends AbstractEntity
MessageImageEntity example
MessageImageEntity 示例
@Entity
@Table(name = MessageImageEntity.TABLE_NAME)
@DiscriminatorValue("IMAGE")
@Data
@Builder
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@NoArgsConstructor
public class MessageImageEntity extends MessageEntity
Therefore I have implemented the follow JoinFormula property for get last message into the Chat but the Message Entity that was get does not belong to a specific implementation
因此,我已经实现了以下 JoinFormula 属性,以获取最后一条消息到聊天中,但获得的消息实体不属于特定的实现。
@ManyToOne(fetch = FetchType.LAZY)
@JoinFormula("("
+ "SELECT M.Messages_id "
+ "FROM Messages M "
+ "LEFT OUTER JOIN Messages_Image MI ON M.Messages_id = MI.Messages_id "
+ "LEFT OUTER JOIN Messages_Text MT ON M.Messages_id = MT.Messages_id "
+ "LEFT OUTER JOIN Messages_Url MU ON M.Messages_id = MU.Messages_id "
+ "WHERE M.Chat_id = Chats_id "
+ "ORDER BY M.Created_at DESC "
+ "LIMIT 1"
+ ")")
protected MessageEntity lastMessage;
Somebody know How Can I do this query? Thanks, Greetings
有人知道我如何执行此查询吗?谢谢,问候。
英文:
I try to find the best way to implement a calculated property witch query the latest message into the chat entity.
The Message entity is implemented as a class hierarchy according to the type of the message (Image, Text, Url ...)
@Entity
@Table(name = MessageEntity.TABLE_NAME)
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "Type", discriminatorType = DiscriminatorType.STRING)
@NamedEntityGraphs({
@NamedEntityGraph(name = MessageEntity.GRAPH_MESSAGES_FULL, attributeNodes = {
@NamedAttributeNode(value = "creator", subgraph = UserEntity.GRAPH_USER_BASIC),
@NamedAttributeNode(value = "chat")
})
})
@Getter
@Setter
public abstract class MessageEntity extends AbstractEntity
MessageImageEntity example
@Entity
@Table(name = MessageImageEntity.TABLE_NAME)
@DiscriminatorValue("IMAGE")
@Data
@Builder
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@NoArgsConstructor
public class MessageImageEntity extends MessageEntity
Therefore I have implemented the follow JoinFormula property for get last message into the Chat but the Message Entity that was get does not belong to a specific implementation
@ManyToOne(fetch = FetchType.LAZY)
@JoinFormula("("
+ "SELECT M.Messages_id "
+ "FROM Messages M "
+ "LEFT OUTER JOIN Messages_Image MI ON M.Messages_id = MI.Messages_id "
+ "LEFT OUTER JOIN Messages_Text MT ON M.Messages_id = MT.Messages_id "
+ "LEFT OUTER JOIN Messages_Url MU ON M.Messages_id = MU.Messages_id "
+ "WHERE M.Chat_id = Chats_id "
+ "ORDER BY M.Created_at DESC "
+ "LIMIT 1"
+ ")")
protected MessageEntity lastMessage;
Somebody know How Can I do this query? Thanks, Greetings
答案1
得分: 1
我建议最好的方法是使用DTO来处理这个,这是Blaze-Persistence Entity Views的一个完美用例。
Blaze-Persistence是建立在JPA之上的查询构建器,支持JPA模型之上的许多高级DBMS功能。我在其之上创建了Entity Views,以便轻松映射JPA模型和自定义接口定义的模型,类似于强大的Spring Data Projections。思路是您可以按照自己喜欢的方式定义目标结构,并通过JPQL表达式将属性(getter)映射到实体模型。由于属性名称通常用作默认映射,因此在大多数情况下,您不需要显式映射,因为80%的用例是使用实体模型的子集的DTO。
您的模型的DTO映射可能看起来像下面这样简单
@EntityView(MessageEntity.class)
interface MessageEntityDto {
Integer getId();
// 其他字段
}
@EntityView(Chat.class)
interface ChatDto {
Integer getId();
@Limit(limit = "1", order = "created DESC")
@Mapping("messages")
MessageEntityDto getLatestMessage();
}
查询只是将实体视图应用于查询的问题,最简单的方法只是按id查询。
ChatDto dto = entityViewManager.find(entityManager, ChatDto.class, id);
但Spring Data集成允许您几乎像Spring Data Projections一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
它只会获取您告诉它要获取的映射。
英文:
I'd say the best approach is to use DTOs for this, which is a perfect use case for Blaze-Persistence Entity Views.
Blaze-Persistence is a query builder on top of JPA which supports many of the advanced DBMS features on top of the JPA model. I created Entity Views on top of it to allow easy mapping between JPA models and custom interface defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure the way you like and map attributes(getters) via JPQL expressions to the entity model. Since the attribute name is used as default mapping, you mostly don't need explicit mappings as 80% of the use cases is to have DTOs that are a subset of the entity model.
A DTO mapping for your model could look as simple as the following
@EntityView(MessageEntity.class)
interface MessageEntityDto {
Integer getId();
// Other fields
}
@EntityView(Chat.class)
interface ChatDto {
Integer getId();
@Limit(limit = "1", order = "created DESC")
@Mapping("messages")
MessageEntityDto getLatestMessage();
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
ChatDto dto = entityViewManager.find(entityManager, ChatDto.class, id);
But the Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
It will only fetch the mappings that you tell it to fetch
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论