0

基本的に投稿/コメントのような機能を持つアプリケーションがあります。Post エンティティから Post インデックス ページをレンダリングし、最新のコメントと作成者を Comment エンティティから表示するアプリケーションが必要です。

私のデータベース/テーブル構造は(IDはプライマリであり、そのままでは表示されません)、サンプルデータは次のとおりです。

create table post
(
    id    int auto_increment,
    title text not null,
    constraint post_id_uindex
        unique (id)
);

id,title
1,This is test post number 1
4,This is test post number 2
5,This is test post number 3

create table comment
(
    id         int auto_increment,
    comment    text     null,
    author     text     null,
    created_at datetime null,
    post_id    int      null,
    constraint comment_id_uindex
        unique (id),
    constraint comment_post_id_fk
        foreign key (post_id) references post (id)
);

id,comment,author,created_at,post_id
1,Nice Post this is,Stephen,2021-08-03 16:49:22,1
2,Another nice post,Billy,2021-08-03 16:49:44,1
3,I didn't like the post at all,Karen,2021-08-04 10:57:05,1

2 つのエンティティに双方向マッピングを設定しました。

@Entity
public class Comment {
    private int id;
    private String comment;
    private String author;
    private Timestamp createdAt;
    private Post postByPostId;

    @Id
    @Column(name = "id")
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Basic
    @Column(name = "comment")
    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    @Basic
    @Column(name = "author")
    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    @Basic
    @Column(name = "created_at")
    public Timestamp getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Timestamp createdAt) {
        this.createdAt = createdAt;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Comment comment1 = (Comment) o;
        return id == comment1.id && Objects.equals(comment, comment1.comment) && Objects.equals(author, comment1.author) && Objects.equals(createdAt, comment1.createdAt);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, comment, author, createdAt);
    }

    @ManyToOne
    @JoinColumn(name = "post_id", referencedColumnName = "id")
    public Post getPostByPostId() {
        return postByPostId;
    }

    public void setPostByPostId(Post postByPostId) {
        this.postByPostId = postByPostId;
    }
}

@Entity
public class Post {
    private int id;
    private String title;
    private Collection<Comment> commentsById;

    @Id
    @Column(name = "id")
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Basic
    @Column(name = "title")
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Post post = (Post) o;
        return id == post.id && Objects.equals(title, post.title);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, title);
    }

    @OneToMany(mappedBy = "postByPostId")
    public Collection<Comment> getCommentsById() {
        return commentsById;
    }

    public void setCommentsById(Collection<Comment> commentsById) {
        this.commentsById = commentsById;
    }
}

私が使用している PostRepository @Query は以下のとおりです。クエリ自体は生の SQL として機能し、最新のコメント データを含む投稿を取得します。

id,title,id,comment,author,created_at,post_id
1,This is test post number 1,3,I didn't like the post at all,Karen,2021-08-04 10:57:05,1
4,This is test post number 2,,,,,
5,This is test post number 3,,,,,

しかし、${post.commentsById} を使用して Thymeleaf テンプレートのコメント フィールドにアクセスしようとすると、@Query コマンドから結合された 1 つのコメント オブジェクトのみを表示することを望んでいたすべてのコメントが表示されます。@Query を削除すると、同じことが行われ、この場合 @Query が無意味になることもわかります。

これを正しく設定する方法について誰か教えてもらえますか?前もって感謝します。

@Repository
public interface PostRepository extends JpaRepository<Post, Long> {

    @Query(value = "select p.*, c.* from post p left join (select a.* from comment a join (select max(created_at) created_at from comment group by post_id) b on a.created_at = b.created_at) c on p.id = c.post_id", nativeQuery = true)
    List<Post> findAll();
}

post.html Thymeleaf テンプレート

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Posts</title>
</head>
<body>
<header>
    <div class="text-center m-5">
        <h1 class="display-6">Posts
            <small class="text-muted" th:text="${title}"></small>
        </h1>
    </div>
</header>

<main>
    <table>
        <thead>
        <tr>
            <th>Post ID</th>
            <th>Post Title</th>
            <th>Latest Comment ID</th>
            <th>Latest Comment</th>
            <th>Author</th>
            <th>Created At</th>
        </tr>
        </thead>
        <tbody>
        <tr th:each="post : ${posts}">
            <td th:text="${post.getId} ?: '-'">-</td>
            <td th:text="${post.title} ?: '-'">-</td>
            <td th:text="${post.commentsById} ?: '-'"></td>
        </tr>
        </tbody>
    </table>
</main>

</body>
</html>

@Query からの最新のコメントではなく、Comment オブジェクト配列を使用して HTML をレンダリングしました

Post ID Post Title  Latest Comment ID   Latest Comment  Author  Created At
1   This is test post number 1  [com.example.demo.entity.Comment@6d578e15, com.example.demo.entity.Comment@e74e80e, com.example.demo.entity.Comment@42b0db5]
4   This is test post number 2  []
5   This is test post number 3  []
4

2 に答える 2