JPA OneToMany和ManyToOne抛出:实体列映射中的重复列(应使用insert =“false”update =“false”进行映射)

时间:2012-12-11 00:45:59

标签: java hibernate jpa one-to-many many-to-one

我有三个类,其中一个名称是User,这个用户有其他类实例。像这样;

public class User{
    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL)
    public List<APost> aPosts;

    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL)
    public List<BPost> bPosts;
}




   public class BPost extends Post {

    @ManyToOne(fetch=FetchType.LAZY)    
    public User user;
 }

    public class APost extends Post {

     @ManyToOne(fetch=FetchType.LAZY) 
     public User user;
 }

它的工作方式与此类似但在db中生成emty表。哪个必须包含外键。当我尝试使用mappedBy和JoinColumn annotains时,我失败了。我该如何解决这个问题?

额外信息:

当我改变时;

 @ManyToOne(fetch=FetchType.LAZY)
 @JoinColumn(name="id")
 public User user;

 @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="id")
 public List<APost> aPosts;

我正在

发生JPA错误(无法构建EntityManagerFactory):实体映射中的重复列:models.post.APost列:id(应使用insert =“false”update =“false”映射)

最终编辑:最后,我对jpa注释完全错了。 :(当我改变

@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="id")

@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="user_id")

everthing工作正常。 :)

3 个答案:

答案 0 :(得分:64)

我不确定您的问题(“空表”等的含义,或mappedByJoinColumn无效的方式)。

我认为你试图建立双向关系。

首先,你需要决定哪一方“拥有”这种关系。 Hibernate将在这方面建立关系基础。例如,假设我让Post方拥有关系(我正在简化你的例子,只是为了保持关键),映射将如下所示:

(希望语法正确。我只是通过记忆来写它们。但是这个想法应该没问题)

public class User{
    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")
    private List<Post> posts;
}


public class Post {
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="user_id")
    private User user;
}

通过这样做,Post的表格将有一个存储关系的列user_id。 Hibernate通过user中的Post来获取关系(而不是posts中的User。如果您有Post的{​​{1}},您会注意到差异1}}但遗漏了user的{​​{1}})。

您提到Userposts无效。但是,我相信这实际上是正确的方法。请告诉我这种方法是否适用于您,并提供有关该问题的更多信息。我认为这个问题是由于别的原因造成的。


编辑:

关于使用mappedBy的一些额外信息,因为它通常会引起混淆。在JoinColumn中,我们将“属性名称”放在双向关系的反面,而不是表列名。

答案 1 :(得分:27)

正如我在this article和我的书High-Performance Java Persistence中所解释的那样,你绝不应该使用单向@OneToMany注释,因为:

  1. 它会生成效率低下的SQL语句
  2. 它创建了一个额外的表,增加了数据库索引的内存占用
  3. 现在,在您的第一个示例中,双方都拥有该关联,并this is bad

    虽然@JoinColumn会让@OneToMany方负责协会,但它绝对不是最佳选择。因此,请始终使用mappedBy侧的@OneToMany属性。

    public class User{
        @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")
        public List<APost> aPosts;
    
        @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")
        public List<BPost> bPosts;
    }
    
    public class BPost extends Post {
    
        @ManyToOne(fetch=FetchType.LAZY)    
        public User user;
    }
    
    public class APost extends Post {
    
         @ManyToOne(fetch=FetchType.LAZY) 
         public User user;
    }
    

答案 2 :(得分:-3)

由于您将直接保存APost和BPost,这意味着APost和BPost将成为关系所有者。由于用户不拥有该关系,因此@OneToMany注释中将存在属性mappedBy。

public class User{
    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL,mappedBy="user", targetEntity = APost.class)
    public List<APost> aPosts;

    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL,mappedBy="user", targetEntity = BPost.class)
    public List<BPost> bPosts;
}

public class BPost extends Post {
    @ManyToOne(fetch=FetchType.LAZY)  
    @JoinColumn(name="user_id",referencedColumnName="id")  
    public User user;
}

public class APost extends Post {
    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name="user_id",referencedColumnName="id")
    public User user;
}

@JoinColumn注释将负责在Apost和BPost中添加外键。