user1048282
user1048282

Reputation: 810

How to correctly persist one-to-many to many relation

I'm getting

Caused by: org.postgresql.util.PSQLException: ERROR: null value in column "post_id" violates not-null constraint

when I'm trying to persist following Entities. The relation is one Post to many post comments that have many more post comments. I would like the relation as well to be unidirectional if possible. Can you point out what I'm doing wrong.

SQL:

    CREATE TABLE post
    (
     id    BIGSERIAL PRIMARY KEY,
     title TEXT
    );

    CREATE TABLE post_comment
    (
     id      BIGSERIAL PRIMARY KEY,
     review  TEXT,
     post_id BIGINT NOT NULL,

     CONSTRAINT post_comment_fk FOREIGN KEY (post_id)
        REFERENCES post (id)
    );

    CREATE TABLE more_post_comment
    (
     id      BIGSERIAL PRIMARY KEY,
     another  TEXT,
     post_comment_id BIGINT NOT NULL,

     CONSTRAINT more_post_comment_fk FOREIGN KEY (post_comment_id)
        REFERENCES post_comment (id)
    );

Repository:

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

Post:

    @Entity(name = "Post")
    @Table(name = "post")
    @Data
    public class Post {
 
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String title;
 
        @OneToMany(cascade = CascadeType.ALL)
        @JoinColumn(name = "post_id")
        private List<PostComment> comments = new ArrayList<>();

     }

PostComment:

    @Entity(name = "PostComment")
    @Table(name = "post_comment")
    @Data
    public class PostComment {
 
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String review;

        @OneToMany(cascade = CascadeType.ALL)
        @JoinColumn(name = "post_comment_id")
        private List<MorePostComment> morePostComment = new ArrayList<>();
    }

MorePostComment:

    @Entity(name = "MorePostComment")
    @Table(name = "more_post_comment")
    @Data
    public class MorePostComment {
 
       @Id
       @GeneratedValue(strategy = GenerationType.IDENTITY)
       private Long id;
       private String another;
   }

Test:

@SpringBootTest
class Test {

    @Autowired
    private PostRepository postRepository;

    @Test
    public void should() {

        Post post = new Post();
        post.setTitle("title");

        MorePostComment morePostComment = new MorePostComment();
        morePostComment.setAnother("another");

        List<MorePostComment> morePostComments = new ArrayList<>();
        morePostComments.add(morePostComment);

        PostComment postComment = new PostComment();
        postComment.setReview("asd");
        postComment.setMorePostComment(morePostComments);

        List<PostComment> comments = new ArrayList<>();
        comments.add(postComment);
        post.setComments(comments);

        post = postRepository.save(post);

        assertThat(post.getComments()).isNotEmpty();
        assertThat(post.getComments().get(0).getId()).isNotNull();
        assertThat(post.getComments().get(0).getMorePostComment()).isNotEmpty();

    }
}

Upvotes: 0

Views: 236

Answers (1)

Georgii Lvov
Georgii Lvov

Reputation: 2701

Please add nullable = false to your @JoinColumn annotations:

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "post_id", nullable = false)
    private List<PostComment> comments = new ArrayList<>();

and

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "post_comment_id", nullable = false)
    private List<MorePostComment> morePostComment = new ArrayList<>();

Hint: you don't need @Repository annotation above your PostRepository because it extends JpaRepostirory and spring knows that repository bean should be created.

Upvotes: 2

Related Questions