Рубрики
Без рубрики

Как сопоставить последний дочерний элемент родительской сущности с помощью формулы соединения Hibernate

Узнайте, как работает аннотация формулы соединения Hibernate и как ее можно использовать для сопоставления последнего дочернего элемента родительской сущности JPA.

Автор оригинала: Vlad Mihalcea.

Вступление

В этой статье я собираюсь объяснить, как работает аннотация формулы соединения Hibernate и как вы можете использовать ее для сопоставления последнего дочернего элемента родительской сущности.

Как ранее объяснялось , @JoinFormula является очень удивительной аннотацией, которая позволяет настраивать способ объединения сущностей за пределами JPA @JoinColumn возможностей.

Модель предметной области

Для предстоящих тестовых случаев мы будем использовать следующие объекты:

Объект Комментарий к сообщению отображается следующим образом:

@Entity(name = "PostComment")
@Table(name = "post_comment")
public class PostComment {

    @Id
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    private Post post;

    private String review;

    @Column(name = "created_on")
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdOn;

    //Getters and setters omitted for brevity
}

Не только Комментарий к сообщению имеет @ManyToOne связь с Сообщением , но Сообщение также связано с последним Сообщением следующим образом:

@Entity(name = "Post")
@Table(name = "post")
public class Post {

    @Id
    private Long id;

    private String title;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinFormula("""
        (SELECT pc.id
        FROM post_comment pc
        WHERE pc.post_id = id
        ORDER BY pc.created_on DESC
        LIMIT 1)
        """
    )
    private PostComment latestComment;

    //Getters and setters omitted for brevity
}

Атрибут последний комментарий связывает родительскую Публикацию сущность с последней Публикацией комментария дочерней сущностью. Аннотация @JoinFormula позволяет нам определить любой запрос SQL select, чтобы обеспечить связь между двумя сущностями.

Тестирование аннотации формулы соединения в режиме гибернации

Учитывая, что в нашей базе данных есть следующие объекты:

Post post = new Post()
    .setId(1L)
    .setTitle("High-Performance Java Persistence");

entityManager.persist(post);

assertNull(post.getLatestComment());

entityManager.persist(
    new PostComment()
    .setId(1L)
    .setPost(post)
    .setCreatedOn(
        Timestamp.valueOf(
            LocalDateTime.of(2016, 11, 2, 12, 33, 14)
        )
    )
    .setReview("Woohoo!")
);

entityManager.persist(
    new PostComment()
    .setId(2L)
    .setPost(post)
    .setCreatedOn(
        Timestamp.valueOf(
            LocalDateTime.of(2016, 11, 2, 15, 45, 58)
        )
    )
    .setReview("Finally!")
);

entityManager.persist(
    new PostComment()
    .setId(3L)
    .setPost(post)
    .setCreatedOn(
        Timestamp.valueOf(
            LocalDateTime.of(2017, 2, 16, 16, 10, 21)
        )
    )
    .setReview("Awesome!")
);

Когда мы извлекаем сущность Post , мы видим, что атрибут последний комментарий работает должным образом:

Post post = entityManager.find(Post.class, 1L);
PostComment latestComment = post.getLatestComment();

assertEquals("Awesome!", latestComment.getReview());

Вывод

Как я объяснил в своей книге “Высокопроизводительная сохраняемость Java”, если вы не воспользуетесь преимуществами базового поставщика JPA или возможностями реляционной базы данных , вы потеряете множество функций.