【问题标题】:jpa hibernate composite foreign key mappingjpa hibernate 复合外键映射
【发布时间】:2011-03-20 10:05:38
【问题描述】:

我在为某些实体设置 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;

}

我知道子实体不正确,但我不确定如何设置它以获得复合 PK。我知道我需要设置一个 PK 类,但是当一个字段是父类的外键时,我不确定该怎么做。一旦设置完成,父级将如何引用子实体?

感谢任何帮助。

【问题讨论】:

标签: java hibernate jpa


【解决方案1】:

这由JPA 2 spec 第 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 对象中删除级联关系来为插入工作。所以我需要在持久化父元素后插入每个子元素,但它现在是可行的。
  • jpa 1.0 规范。目前我需要使用 jboss 4.2.3,我的理解是 jpa 2.0 将无法在此应用服务器上运行,至少在不换掉一堆库的情况下不会。
【解决方案2】:

我也面临同样的问题并遵循了这个答案,但它没有将子实体与父实体一起保存。这是我所做的更改,它运行良好。进行以下更改 -

// 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)

【讨论】:

    猜你喜欢
    • 2016-09-18
    • 2017-02-21
    • 2019-04-22
    • 1970-01-01
    • 2021-09-19
    • 2023-04-03
    • 2016-06-05
    • 2017-01-30
    • 2012-04-06
    相关资源
    最近更新 更多