我有2个名为Post和PostDetails的实体类。两者都使用MapsId
映射为OneToOne关系并共享主键,如下所示。
Post.java
@Entity
@Table(name = "post")
@Data
public class Post implements Serializable
{
private static final long serialVersionUID = -6698422774799518217L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NaturalId
@Column(name = "title")
private String title;
@OneToOne(mappedBy = "post", cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
private PostDetail detail;
}
PostDetail.java
@Entity
@Table(name = "post_detail")
@Data
public class PostDetail implements Serializable
{
private static final long serialVersionUID = -6699482774799518217L;
@Id
private Long id;
@Column(name = "created_on")
private Date createdOn;
@Column(name = "created_by")
private String createdBy;
@OneToOne(fetch = FetchType.LAZY)
@MapsId
@JoinColumn(name = "id")
@JsonIgnore
private Post post;
}
PostController.java
@RestController
@RequestMapping("/api/v1/post")
public class PostController
{
private final PostRepository postRepository;
private final PostDetailRepository postDetailRepository;
public PostController(PostRepository postRepository, PostDetailRepository postDetailRepository)
{
this.postRepository = postRepository;
this.postDetailRepository = postDetailRepository;
}
@GetMapping(path = "/create")
public List<Post> createAndGetPosts()
{
Post post=new Post();
post.setId(new Random().nextLong());
post.setTitle("First Post");
post=postRepository.saveAndFlush(post);
PostDetail postDetail =new PostDetail();
postDetail.setCreatedBy("Admin");
postDetail.setCreatedOn(Date.from(Instant.now()));
postDetail.setPost(post);
postDetailRepository.saveAndFlush(postDetail);
return postRepository.findAll(Sort.by(Sort.Direction.DESC,"id"));
}
}
在Post Controller类中,我创建Post对象(将其保存为DB),然后将其传递给PostDetail对象,然后使用Spring Data JPA将其保存到数据库中。一切正常。但是,当我立即通过
postRepository.findAll(Sort.by(Sort.Direction.DESC,"id"));
方法获取记录列表时,我在Post内收到PostDetail对象的null
值,如下所示。响应:
[
{
"id": 2,
"title": "First Post",
"detail": null
},
{
"id": 1,
"title": "Post1",
"detail": {
"id": 1,
"createdOn": "2019-06-21T03:31:43.000+0000",
"createdBy": "Admin"
}
}
]
但是,当我再次从前端发送该列表的请求时,我得到了正确的响应。我试图将flush语句和第二个findAll()语句放在请求之前,但没有任何效果。
最佳答案
发生这种情况是因为您收到了与saveAndFlush
返回并存储在post
变量中的实例完全相同的实例。
当您执行Post.detail
时,Hibernate不会更新postDetail.setPost(post)
。
要解决此问题,您可以手动设置detail
或在保存后从缓存中逐出Post
实例,这会迫使休眠状态从数据库重新加载它。