Как сделать запрос polymorphi c с аннотацией Hibernate JoinFormula? - PullRequest
0 голосов
/ 02 августа 2020

Я пытаюсь найти лучший способ реализовать вычисляемое свойство, которое запрашивает последнее сообщение в сущности чата.

Сущность сообщения реализована как иерархия классов в соответствии с типом сообщения (Изображение, Текст, 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

@Entity
@Table(name = MessageImageEntity.TABLE_NAME)
@DiscriminatorValue("IMAGE")
@Data
@Builder
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@NoArgsConstructor
public class MessageImageEntity extends MessageEntity

Поэтому я реализовал следующее свойство JoinFormula для получения последнего сообщения в чат, но полученный объект сообщения делает не относится к определенной c реализации

@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;

Кто-нибудь знает, как я могу выполнить этот запрос? Спасибо, Привет

1 Ответ

1 голос
/ 03 августа 2020

Я бы сказал, что лучший подход - использовать для этого DTO, что является идеальным вариантом использования Blaze-Persistence Entity Views .

Blaze-Persistence - это построитель запросов на top of JPA, который поддерживает многие расширенные функции СУБД поверх модели JPA. Я создал Entity Views поверх него, чтобы упростить сопоставление между моделями JPA и моделями, определяемыми пользовательским интерфейсом, что-то вроде Spring Data Projection на стероидах. Идея состоит в том, что вы определяете свою целевую структуру так, как вам нравится, и сопоставляете атрибуты (геттеры) через выражения JPQL с моделью сущности. Поскольку имя атрибута используется в качестве сопоставления по умолчанию, вам в большинстве случаев не нужны явные сопоставления, поскольку в 80% случаев использования должны быть DTO, которые являются подмножеством модели сущности.

Сопоставление DTO для вашей модели может выглядеть так просто, как следующее

@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();
}

Запрос - это вопрос применения представления сущности к запросу, самый простой из которых - это просто запрос по идентификатору.

ChatDto dto = entityViewManager.find(entityManager, ChatDto.class, id);

Но интеграция Spring Data позволяет вам использовать его почти как Spring Data Projection: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring -data-features

Он будет извлекать только сопоставления, которые вы говорите ему.

...