Java 使用Map的JPA集合
所以我有一个使用JPA、Hibernate和Spring数据的小概念证明。在此POC中,我创建了一个Java 使用Map的JPA集合,java,spring,hibernate,jpa,spring-data,Java,Spring,Hibernate,Jpa,Spring Data,所以我有一个使用JPA、Hibernate和Spring数据的小概念证明。在此POC中,我创建了一个Post实体和一个Comment实体。Post实体包含注释映射map 我在将多个注释实体持久化到映射中时遇到问题,因为我使用注释实体@Id列作为映射的键。基本上,如果我没有显式地设置注释的id,Hibernate会将它们识别为同一个实体,并且只保留其中一个 我发现我可以通过指定垃圾键来持久化Map,一旦持久化,MySql autonumber将替换垃圾键。这导致了一个问题,当前映射中的键将不会接收
Post
实体和一个Comment
实体。Post
实体包含注释映射map
我在将多个注释
实体持久化到映射
中时遇到问题,因为我使用注释
实体@Id
列作为映射的键。基本上,如果我没有显式地设置注释的id,Hibernate会将它们识别为同一个实体,并且只保留其中一个
我发现我可以通过指定垃圾键来持久化Map
,一旦持久化,MySql autonumber将替换垃圾键。这导致了一个问题,当前映射中的键将不会接收数据库设置的新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 */
}
@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()));
}
@测试
公共void insertTest2(){
注释=新注释();
注释comment2=新注释();
最终字符串body1=“这是一个映射测试”;
最终字符串body2=“这是另一个映射测试”;
意见。主体(主体1);
评注2.主体(主体2);
Post Post=新Post();
post.setPostDate(新日期());
职位名称(“第一职位”);
post.getComments().put(1,comment);//设置垃圾ID
post.getComments().put(2,comment2);//设置垃圾ID
评论.setPost(post);
评论2.设置邮政(邮政);
保存(post);
Post-dbpost=repository.findOne(Post.getPostId());
Map comments=dbpost.getComments();
//使用旧id测试失败
assertTrue(comments.containsKey(comment.getCommentId());
//这里也一样
assertTrue(comments.containsKey(comment2.getCommentId());
}
还要注意,这是一种双向关系
我应该指定垃圾键来持久化映射中的实体吗
不会。一旦真实ID受到影响,地图就会处于不一致状态。映射的键应该是不可变的
我的方法全错了吗?如果是这样,有什么更好的方法
坦率地说,我并不认为使用映射来保存ID注释有什么意义。实体管理器已经能够获得ID注释了。我只需要使用集合或列表
另一种方法是在将注释添加到映射之前保留注释并刷新实体管理器,以确保它们已经具有真实的ID。为什么需要映射
?为什么不是一个简单的注释列表?因为映射的键是实体的id。或者这就是你的POC的全部内容?@RodrigoSasaki我的POC的全部目的就是学习如何使用地图。这只是为了教育目的。这只是一个POC,它的全部目的是学习如何使用地图。很抱歉,我应该在问题中指出我不想偏离使用地图的方法。但是你的意思是保留评论然后把它们添加到地图上?哎呀,我真害怕。