简体   繁体   English

错误 - 非空属性引用 null 或瞬态值

[英]Error - not-null property references a null or transient value

I'm a newbie in Spring. I make an API that based on relationship between two tables, for that use a OneToMany annotation & for API test I've postman. My aim is to save requested data in two seperate entities which are mentioned hereunder.我是 Spring 的新手。我根据两个表之间的关系制作了一个 API,为此使用了 OneToMany 注释,对于 API 测试,我有 postman。我的目标是将请求的数据保存在下面提到的两个单独的实体中. When I try to post a data in postman: 1-3 fields are related to Post entity whereas text field belong to Comment entity (comments is joining field)当我尝试在 postman 中发布数据时:1-3 个字段与 Post 实体相关,而文本字段属于 Comment 实体(评论正在加入字段)

{
"title": "Post1",
"description": "Post 1 description",
"content": "Post 1 content",
"comments": [
    {
        "text": "Java best selling book"
    },
    {
        "text": "Exploring spring boot"
    }
]

} }

I get an error as follows:我收到如下错误:

Hibernate: insert into posts (content, description, title) values (?, ?, ?)
2021-09-01 11:55:09.786 TRACE 9884 --- [nio-8089-exec-2] o.h.type.descriptor.sql.BasicBinder      
: binding parameter [1] as [VARCHAR] - [Post 1 content]
2021-09-01 11:55:09.786 TRACE 9884 --- [nio-8089-exec-2] o.h.type.descriptor.sql.BasicBinder      
: binding parameter [2] as [VARCHAR] - [Post 1 description]
2021-09-01 11:55:09.786 TRACE 9884 --- [nio-8089-exec-2] o.h.type.descriptor.sql.BasicBinder      
: binding parameter [3] as [VARCHAR] - [Post1]
2021-09-01 11:55:09.815 ERROR 9884 --- [nio-8089-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    
: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception 
[Request processing failed; nested exception is 
org.springframework.dao.DataIntegrityViolationException: not-null property references a null 
or transient value : com.techspring.entity.Comment.post; nested exception is 
org.hibernate.PropertyValueException: not-null property references a null or transient value : 
com.techspring.entity.Comment.post] with root cause

My MVCs are as follows:我的 MVC 如下:

Post.java邮编java

@Entity
@Table(name = "posts")
public class Post {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  private String title;
  private String description;
  private String content;
  @OneToMany(cascade = CascadeType.ALL,
        fetch = FetchType.LAZY,
        mappedBy = "post")
  private Set<Comment> comments = new HashSet<>();

  GET, SET;

Comment.java评论.java

@Entity
@Table(name = "comments")
public class Comment {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  private String text;

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

  Get, Set;

PostController.java PostController.java

RestController public class PostController { RestController 公共 class PostController {

@Autowired
private PostRepository postRepository;

@PostMapping("/posts")
public Post createPost(@Valid @RequestBody Post post) {
    return postRepository.save(post);
}      

CommentController.java CommentController.java

@RestController
public class CommentController {

@Autowired
private CommentRepository commentRepository;

@Autowired
private PostRepository postRepository;


@PostMapping("/posts/{postId}/comments")
public Comment createComment(@PathVariable (value = "postId") Long postId,
                             @Valid @RequestBody Comment comment) {
    return postRepository.findById(postId).map(post -> {
        comment.setPost(post);
        return commentRepository.save(comment);
    }).orElseThrow(() -> new ResourceNotFoundException("PostId " + postId + " not found"));

Appreciate for the help.感谢您的帮助。

The way you do it Comment comment<\/code> is a new transient entity which is related to an already maintained entity of post<\/code> .你这样做的方式Comment comment<\/code>是一个新的临时实体,它与已经维护的post<\/code>实体相关。 During save first hibernate will try to update post to match with that comment but that comment does not exist yet and so it fails.在保存期间,第一次休眠将尝试更新帖子以匹配该评论,但该评论尚不存在,因此失败。

A better workflow for you would be the following.对您来说更好的工作流程如下。

It makes better sense to return the Post with all coments as return and also just append the new comment to an already existing post.返回带有所有评论的帖子更有意义,并且只需将新评论附加到已经存在的帖子中。 That way hibernate will first go and create the comment entity and then relate it to post which already exists and will not face any problem.这样,hibernate 将首先创建评论实体,然后将其与已经存在且不会遇到任何问题的帖子相关联。

@PostMapping("/posts/{postId}/comments")
public Post createComment(@PathVariable (value = "postId") Long postId,
                             @Valid @RequestBody Comment comment) {
    Optional<Post> postOpt = postRepository.findById(postId);
      if (postOpt.isPresent()) {
        comment.setPost(postOpt.get()); <----------------
        postOpt.get().getComments().add(comment);
        postRepository.save(postOpt.get());
        return postOpt.get();
      } else {
        throw new ResourceNotFoundException("PostId " + postId + " not found");
      }

   }

I had a similar issue and to solve it you need to set the parent into child object.我有一个类似的问题,要解决它,您需要将父对象设置为子对象。 It'll be something like this会是这样的

post.getComments().stream().forEach(c -> c.setPost(post));

I had a similar issue, and to solve it I had to change the Entity Object to nullable.我有一个类似的问题,为了解决它,我必须将实体 Object 更改为可为空。

@Column( name = "dog", nullable = true ) private String dog; @Column( name = "dog", nullable = true ) private String dog;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM