Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Map的JPA集合_Java_Spring_Hibernate_Jpa_Spring Data - Fatal编程技术网

Java 使用Map的JPA集合

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将替换垃圾键。这导致了一个问题,当前映射中的键将不会接收

所以我有一个使用JPA、Hibernate和Spring数据的小概念证明。在此POC中,我创建了一个
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,它的全部目的是学习如何使用地图。很抱歉,我应该在问题中指出我不想偏离使用地图的方法。但是你的意思是保留评论然后把它们添加到地图上?哎呀,我真害怕。