JPA Hibernate复合外键映射

11

我在设置一些实体的JPA映射时遇到了麻烦。我定义了一个父实体,如下所示。

@Entity
@Table(name="EIF_INSTANCE_HDR")
public class InstanceEntity implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(generator="eif_inst_gen")
    @SequenceGenerator(name="eif_inst_gen",sequenceName="EIF_INSTANCE_SEQ")
    @Column(name = "EAIH_ID")
    private Long eaihid;

    @Column(name = "EAD_ID")
    private Long eadid;

    @OneToMany(targetEntity=InstanceNotifyEntity.class, mappedBy="instance",fetch=FetchType.EAGER, cascade = CascadeType.ALL)
    private List<InstanceNotifyEntity> userDetails = new ArrayList<InstanceNotifyEntity>();

}

我有一个具有复合键的子实体,并且具有对此表的主键的外键,如下所示:

@Entity
@Table(name="EIF_INST_NOTIFIED")
public class InstanceNotifyEntity implements Serializable{

    private static final long serialVersionUID = 1L;
    
    @Id
    @ManyToOne
    @JoinColumn(name="EAIH_ID", referencedColumnName="EAIH_ID")
    private InstanceEntity instance;
    
    @Id
    @Column(name="USER_ID")
    private Long userId;

    @Column(name="COMMENT_TXT")
    private String commentText;

}

我知道子实体是错误的,但我不确定如何设置它以拥有一个复合主键。我知道需要设置一个主键类,但当一个字段是指向父类的外键时,我不知道该如何做。一旦设置好了,父类如何引用子实体?


请见https://dev59.com/AUzSa4cB1Zd3GeqPq_Am#2563009 - axtavt
2个回答

15

这由JPA 2规范第2.4.1节“对应派生标识的主键”控制。该部分包含两个直接适用于您问题的示例。

根据规范描述,在此情况下表示子实体的键有两种方式:

  • @IdClass
  • @EmbeddedId

下面是EmbeddedId方式的大致概述。我任意选择了EmbeddedId,但在IdClassEmbeddedId之间进行选择是重要的。你可能会有不同的选择。

// Child entity's composite primary key
@Embeddable
public class InstanceNotifyEntityId implements Serializable {
    Long eaihId;
    Long userId;
}

// Child entity
@Entity
@Table(name="EIF_INST_NOTIFIED")
public class InstanceNotifyEntity implements Serializable {
    @AttributeOverrides({
      @AttributeOverride(name="userId", column = @Column(name="USER_ID"))
      @AttributeOverride(name="eaihId", column = @Column(name="EAIH_ID"))
    })
    @EmbeddedId
    InstanceNotifyEntityId id;

    @MapsId("eaihId")
    @ManyToOne
    InstanceEntity instance;

    // ...
 }

父实体需要做一项更改: userDetails属性的mappedBy应该是"id.eaihId"。我认为就是这样,但我以前没有使用过完全相同的实体,可能会遗漏一些东西...如果您发现错误,请发帖提醒。


谢谢,这个大部分都可以用。不幸的是我没有使用jpa 2.0,所以@MapsId注释不可用。我已经通过从父实体userDetails对象中删除级联关系来使插入工作正常。因此,在持久化父元素后,我需要插入每个子元素,但现在它是可行的。 - broschb
JPA 1.0规范。目前我需要使用jboss 4.2.3,我的理解是JPA 2.0在这个应用服务器上不起作用,至少不能不交换一堆库。 - broschb

1
我也遇到了同样的问题,按照这个答案进行操作,但是它没有保存子实体和父实体。以下是我所做的更改,现在已经正常工作。请进行以下更改 -
// Child entity's composite primary key class

public class InstanceNotifyEntityId implements Serializable {

    @Column(name = "USER_ID")
    Long userId;

    @JoinColumn(name = "EAIH_ID")
    @ManyToOne  
    InstanceEntity instance
}

// Child entity which contain composite primary key as a EmbeddedId, 
// no need to define any relationship here as we already define 
// the relationship in composite key class. 

@Entity
@Table(name = "EIF_INST_NOTIFIED")
public class InstanceNotifyEntity implements Serializable {

    @EmbeddedId
    InstanceNotifyEntityId id;
}


// Parent entity (parent entity mappedby should be your composite 
// key class instance.child class object which already have the 
// join column mapping with "EAID_ID")  

@Entity
@Table(name = "EIF_INSTANCE_HDR")
public class InstanceEntity implements Serializable {

    @OneToMany(mappedBy = "id.instance,fetch=FetchType.EAGER, cascade = CascadeType.ALL)
    private List<InstanceNotifyEntity> userDetails = new ArrayList<InstanceNotifyEntity>();
}

在保存父实体时,将父对象设置为复合键,例如 id.setInstance(parent entire obj)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接