【发布时间】:2013-04-05 18:23:47
【问题描述】:
所以我有一个使用 JPA、Hibernate 和 Spring Data 的小型概念证明。在这个 POC 中,我创建了一个 Post 实体和一个 Comment 实体。 Post 实体包含 cmets Map<Integer,Comment> 的映射。
我在将多个 Comment 实体持久保存到 Map 时遇到问题,因为我使用 Comment 实体 @Id 列作为地图的键。基本上,如果我没有明确设置 Comment 的 id,Hibernate 会将它们识别为同一个实体,并且只保留其中一个。
我发现我可以通过指定垃圾键来持久化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 */
}
Comment.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()));
}
还要注意这是双向关系
【问题讨论】:
-
为什么需要
Map?为什么不是一个简单的List评论?因为地图的键是实体的 id。或者这就是您的 POC 的全部意义所在? -
@RodrigoSasaki 我的 POC 的重点是学习如何使用地图。这仅用于教育目的。
标签: java spring hibernate jpa spring-data