所以我有一个使用 JPA、Hibernate 和 Spring Data 的小型概念证明。在这个 POC 中,我创建了一个Post
实体和一个Comment
实体。该Post
实体包含评论地图Map<Integer,Comment>
。
由于我使用实体列作为地图的键,因此我在将多个Comment
实体持久化时遇到了问题。基本上,如果我没有明确设置Hibernate 的 id,就会将它们识别为同一个实体,并且只保留其中一个。Map
Comment
@Id
Comment
我发现我可以Map
通过指定垃圾键来持久化,一旦持久化,MySql 自动编号将替换它。这导致了一个问题,当前映射中的键不会接收commentId
到数据库设置的新值。这导致我的单元测试失败。
所以基本上我有三个问题?
- 我应该指定垃圾键来持久化地图中的实体吗?
- 我的方法全错了吗?如果是这样,有什么更好的方法?
- 如果垃圾键没问题,插入后如何刷新它们?
Post.java
@Entity
@Table(name = "POST")
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "POST_ID")
private Integer postId;
@Column(name = "TITLE")
private String title;
@OneToMany(mappedBy = "post", cascade = CascadeType.ALL)
@MapKeyColumn(name="COMMENT_ID")
private Map<Integer, Comment> comments = new HashMap<Integer, Comment>();
/** Accessors (Get/Set) **/
/** HashCode & Equals that does not consider the postId field or the Map */
}
评论.java
@Entity
@Table(name="COMMENT")
public class Comment {
@Id
@Column(name="COMMENT_ID")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer commentId;
@Column(name="BODY")
private String body;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="POST_ID")
private Post post;
/** Accessors (Get/Set) **/
/** HashCode & Equals that does not consider the commentId field or the Post */
}
单元测试
@Test
public void insertTest2(){
Comment comment = new Comment();
Comment comment2 = new Comment();
final String body1 = "This is a map test";
final String body2 = "This is another map test";
comment.setBody(body1);
comment2.setBody(body2);
Post post = new Post();
post.setPostDate(new Date());
post.setTitle("First Post");
post.getComments().put(1,comment); //Setting garbage IDs
post.getComments().put(2, comment2); //Setting garbage IDs
comment.setPost(post);
comment2.setPost(post);
repository.save(post);
Post dbpost = repository.findOne(post.getPostId());
Map<Integer, Comment> comments = dbpost.getComments();
//Test fails using old id
assertTrue(comments.containsKey(comment.getCommentId()));
//Same here
assertTrue(comments.containsKey(comment2.getCommentId()));
}
另请注意,这是双向关系