Hibernate(JPA)为同一模型多个@OneToMany

时间:2012-10-12 14:03:08

标签: java hibernate jpa one-to-many

我有两个模特。

@Entity
public class Student
{
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    protected long id;

    @?
    protected Address homeAddress;

    @?
    protected Address schoolAddress;
}

@Entity
public class Address
{
   @Id
   @GeneratedValue(strategy=GenerationType.AUTO)
   protected long id;

   @?
   protected List<Student> students;
}

我需要在homeAddressschoolAddressstudents之上放置哪些JPA / hibernate注释才能使关联工作?

当然,我尝试了很多东西,没有任何效果。 例如,设置

    @ManyToOne
    @JoinColumn (name="student_homeAddress_id", updatable = false, insertable = false)
    protected Address homeAddress;

    @ManyToOne
    @JoinColumn (name="student_schoolAddress_id", updatable = false, insertable = false)
    protected Address schoolAddress;

    @OneToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER)
    @JoinColumns({
    @JoinColumn(name = "student_homeAddress_id", referencedColumnName = "student_homeAddress_id"),
    @JoinColumn(name = "student_schoolAddress_id", referencedColumnName = "student_schoolAddress_id")})
    @IndexColumn(name="students_index")
    protected List<Student> students;

yealds Unable to find column with logical name: student_homeAddress_id in org.hibernate.mapping.Table(Address) and its related supertables and secondary tables。 也尝试使用mappedBy,但只需要一个参数(不能mappedBy="student_homeAddress_id, student_schoolAddress_id"

还考虑将JoinColumns移动到Student平板电脑,但我不确定OneToMany和ManyToOne的注释应该是什么样的,因为我有多个地址,其中JoinColumns没有多大意义

确实有效但未创建关联的事情是:

    @OneToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER)
    @JoinColumn(name="address_id")
    @IndexColumn(name="students_index")
    protected List<Student> students;

使用此功能,当在数据库中存储模型时,即使存储了两端(学生和地址模型),student_homeAddress_id和student_schoolAddress_id也始终为空。

我的想法是在Address表上会有3个额外的列:student_homeAddress_id(homeAddress的Student表中Student的id),student_schoolAddress_id(Student表中Student的id) schoolAddress)和students_index(students列表中基于0的位置)。这应该足够了,对吗?

有什么想法吗?

非常感谢!

2 个答案:

答案 0 :(得分:4)

如果您想要在多个字段中关联@OneToMany的实体,则应使用@JoinTable,以便Hibernate可以为该关系生成2个表。

来自@JoinTable javadoc:

  

连接表通常用于多对多和多对的映射   单向一对多关联。它也可以用于映射   双向多对一/一对多关联,单向   多对一关系,一对一关联(两者兼而有之)   双向和单向的。

     

使用连接表映射具有嵌入的关系时   在关系的拥有方面,包含实体的类   而不是可嵌入的类被认为是   关系。

     

如果缺少JoinTable注释,则默认值为   注释元素适用。假定连接表的名称是   连接在一起的关联主表的表名   (首先拥有一方)使用下划线。

举个例子:

@Entity
@Indexed(index = "causa_penal")
@Table(name = "causas_penales")
public class CausaPenal implements Serializable {



     @Id
     @GeneratedValue(strategy = GenerationType.TABLE)
     @Column(name = "id")
     @DocumentId
     private Integer id;

     @Version
     @Column(name = "opt_lock")
     private Integer version;

     @ManyToMany(cascade = { CascadeType.ALL })
     @JoinTable(name = "causapenal_imputados")
     @IndexedEmbedded(depth = 1)
     private List<ParteMaterial> imputados;

     @ManyToMany(cascade = CascadeType.ALL)
     @JoinTable(name = "causapenal_victimas")
     @IndexedEmbedded(depth = 1)
     private List<ParteMaterial> victimas;

    //Getters and Setters
}

如您所见,我让CausaPenal指向ParteMaterial两次。但是我需要这些列表彼此独立。因此,对于@JoinTable,我告诉Hibernate这个关系必须映射到4个表:CausaPenal实体的“causa_penal”,CausaPenal与imputados字段关系的“causa_penal_imputados”,映射到ParteMaterial实体,并且对于victima和最后,ParteMaterial Entity的表格。

答案 1 :(得分:4)

我们尝试了mael的建议,但我们无法使其发挥作用。

我们最终关注了this

换句话说,我们有OneToMany关系:

Student

protected List<AddressStudentAssociation> addresses;

Address

protected List<AddressStudentAssociation> students;

AddressStudentAssociation

@ManyToOne
@PrimaryKeyJoinColumn(name="STUDENTID", referencedColumnName="id")
private Student student;
@ManyToOne
@PrimaryKeyJoinColumn(name="ADDRESSID", referencedColumnName="id")
private Address address;

加上一个参数将一个地址与另一个地址分开(isHome)。

最后,在Student内,我们有public Address getHomeAddress()遍历addresses列表并返回正确的地址。我们还必须使用注释来使其工作。一般来说不是最佳的但是它有效并且我们已经花费了太多时间来努力使事情发挥作用。 :|