在JPA中使用oneToMany关系时,列中的Postgresql throw null值违反了非null约束

时间:2017-02-19 13:45:32

标签: java postgresql hibernate jpa

我试图测试Hibernate的一对多关系。我将Post和PostComment实体定义如下: 的 Post.java

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

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

    @Id
    @Column(name="post_id")
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Long postId;

    @Column(name="title")
    private String title;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "post",
            orphanRemoval = true)
    private List<PostComment> comments = new ArrayList<>();

    public Post() {};

    public Post(String title) {
        this.title = title;
    }
   // Add getter and setter
}

PostComment.java

    import javax.persistence.*;

@Entity
@Table(name = "post_comment")
public class PostComment {
    @Id
    @Column(name="comment_id")
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Long commentId;

    @Column(name="review")
    private String review;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "post_id")
    private Post post;

    public PostComment() {};
    public PostComment(String review) {
        this.review = review;
    }
    // Add getter and setter
}

PostRepository.java

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

db-changelog.xml

<changeSet id="1" author="dev">
    <createTable tableName="post_comment">
        <column name="comment_id" type = "bigint">
            <constraints nullable="false" primaryKey="true"></constraints>
        </column>
        <column name="review" type="varchar(255)"></column>
    </createTable>
    <createTable tableName="post">
        <column name="post_id" type="bigint">
            <constraints nullable="false" primaryKey="true"></constraints>
        </column>
        <column name="title" type = "varchar(255)"></column>
    </createTable>
</changeSet>

然后,我使用SpringJUnit在PostServiceITTest.java中添加一个新帖子

 import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import java.util.Arrays;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {Application.class})
@WebAppConfiguration
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@ActiveProfiles("devmock")
public class PostServiceITTest {
    @Autowired
    private PostRepository postRepository;

    @Test
    public void testAddPost(){
        Post post = new Post(" Post 1");

        PostComment postComment1 = new PostComment(" Post comment 1");  
        PostComment postComment2 = new PostComment(" Post comment 2");
        post.setComments(Arrays.asList(postComment1,postComment2));

        postRepository.save(post);
    }
}

不幸的是,测试抛出了与null-violate约束相关的Postgresql错误:

    Caused by: org.postgresql.util.PSQLException: ERROR: null value in column "post_id" violates not-null constraint
  Detail: Failing row contains (null,  Post 1).

我非常感谢你的时间。

4 个答案:

答案 0 :(得分:0)

您似乎没有传递post_id的值。

答案 1 :(得分:0)

PostComment课程中,您有一个字段private Post post。我怀疑你是否正在设置那个领域。

一个选项是将Post post作为构造函数参数添加到PostComment类(以及默认构造函数),并将其与Post对象一起实例化,如下所示:

public PostComment(String review, Post post) {
  this.review = review;
  this.post = post;
}

在构建对象时使用:

PostComment postComment1 = new PostComment(" Post comment 1", post);

而不是

PostComment postComment1 = new PostComment(" Post comment 1");

或者另一种方法是在Post类中添加脚手架代码,如:

public void addPostComment(PostComment comment) {
    comments.add(comment);
    comment.setPost(this);
}

并在将PostComment更新/添加到Post类的列表时使用此方法。

答案 2 :(得分:0)

我已经解决了该问题,方法是删除现有数据库并使用spring.jpa.hibernate.ddl-auto=create-drop生成一个新数据库。在我看来。最好在每次对实体结构进行一些重大更改时都执行此操作。完成后,请改回spring.jpa.hibernate.ddl-auto=update

答案 3 :(得分:0)

以下代码可能有效;您也可以在 child 中设置父引用...

{       Post post = new Post(" Post 1");

        PostComment postComment1 = new PostComment(" Post comment 1");  
        postComment1.setPost(post); // < -- here
        PostComment postComment2 = new PostComment(" Post comment 2");
        postComment2.setPost(post); // < -- here

        post.setComments(Arrays.asList(postComment1,postComment2));

        postRepository.save(post); 
}

如果你使用 lombok 生成 toString() 方法,请排除 postComment.post 以避免无限循环(导致 stak 溢出);

@ToString(exclude = { "post" })
public class PostComment{
// ...
}