如何使用JPA批注为复合键创建复合ID类来插入和更新3表

时间:2018-08-01 17:55:20

标签: hibernate jpa spring-data-jpa jpa-2.0 jpa-2.1

有三个表HouseEntity,HousePersonEntity和PersonEntity。

HouseEntity由houseNumber和houseName的唯一组合标识。 该实体没有主键,它具有houseNumber和houseName作为组合键。

PersonEntity具有ID(自动生成)和名称。

HousePersonEntity是逻辑表,用于存储具有多个人ID的一所房子。因此,简而言之,HouseEntity与PersonEntity具有一对多的关系。

JPA实体

@Entity
@Table(name="House")
public class HouseEntity extends AbstractObject implements Serializable {
     @EmbeddedId
     private HouseEntityPK pk;          //Composit key
     //bi-directional many-to-one association to Dependent 
     @OneToMany(mappedBy="primaryKey.houseEntity ", cascade=CascadeType.ALL) 
     private Set<HousePersonEntity > housePersonEntity = new HashSet<HousePersonEntity>(); 

@Embeddable
public class HouseEntityPK implements Serializable {     
    @Column(name = "H_HOUSENUMBER", unique = true, nullable = false)
    private int houseNumber;
    @Column(name = "H_HOUSENAME", unique = true, nullable = false)
    private String houseName;

@Entity
@Table(name="Person")
public class PersonEntity{     
   @Id
   @GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "PERSON_SEQ")
   @Column(name = "ID", unique = true, nullable = false)
   private int id;
   private String name;

@Entity
@Table(name="HouseHavingPersons")
@AssociationOverrides({
    @AssociationOverride(name = "primaryKey.personEntity",joinColumns = @JoinColumn(name = "ID")),
    @AssociationOverride(name = "primaryKey.houseEntity",  joinColumns = { 
                @JoinColumn(name = "H_HOUSENUMBER" , referencedColumnName = "H_HOUSENUMBER") ,
                @JoinColumn(name = "H_HOUSENAME" , referencedColumnName = "H_HOUSENAME") })
        })
public class HousePersonEntity extends AbstractObject implements Serializable {
    @EmbeddedId
    private HousePersonEntityPK pKey= new HousePersonEntityPK();
    @Transient
    public PersonEntity getPersonEntity() {
        return getPrimaryKey().getPersonEntity();
    }
    @Transient
    public HouseEntity getHouseEntity() {
        return getPrimaryKey().getHouseEntity();
    }

@Embeddable
public class HousePersonEntityPK implements Serializable {     
    @ManyToOne(cascade=CascadeType.ALL)
    private HouseEntity houseEntity ;
    @ManyToOne(cascade=CascadeType.ALL)
    private PersonEntity personEntity ;

HouseHavingPersons中,当我插入数据时,它首先插入House中,然后在HouseHavingPersons表中插入与该房屋相关的所有人物姓名,其中包含房屋和人物的所有详细信息在里面。这很好。对于所有新的关联,它首先插入House中,然后填充到HouseHavingPersons中。

当我尝试更新任何记录(例如,如果表House中已经存在houseNumber且仅更新了几列并且添加或更新了新人员)时,问题开始。它仅更新House表,而在HouseHavingPersons中没有任何输入。我究竟做错了什么?此方案还有其他方法吗?任何帮助将不胜感激。

已编辑..以获取更多说明

嗨,尼古拉斯,我得到了一个链接,该链接具有类似的示例,仅供您参考。 http://www.codejava.net/frameworks/hibernate/hibernate-many-to-many-association-with-extra-columns-in-join-table-example-请参阅为复合密钥创建复合ID类。

这是我在“更新中未插入”的问题。更新时,我能够更新House表格,但HousePersonEntity上没有更新,并且无限循环。

要测试的场景是 1.如果没有关于房屋编号的数据,请插入房屋,然后插入相关的人员编号以及人员编号,居所编号和姓名。

  1. 如果已经存在房屋ID条目,则将更新的人员条目插入HousePersonEntity。

  2. 如果房屋表中已经存在该条目,但是需要更新房屋的几列,则更新该房屋ID的房屋表,然后在HousePersonEntity中插入。在HousePersonEntity中,如果存在条目,则更新现有字段,并为HousePersonEntity中的新数据插入记录。

所以一所房子可以有多个人,并且该关联应该存在于HousePersonEntity表中。

1 个答案:

答案 0 :(得分:0)

不清楚您的问题是什么。您说您在Person上添加了House,但没有输入HouseHavingPersons。这是因为House没有关系。

 @OneToMany(mappedBy="primaryKey.houseEntity ", cascade=CascadeType.ALL) 
 private Set<HousePersonEntity > housePersonEntity = new HashSet<HousePersonEntity>(); 

这里mappedByHouseHavingPersonsHousePersonEntity)拥有关系。这意味着您必须为该实体插入Persons的新House并将其保留。将它们添加到Set<HousePersonEntity> housePersonEntity不会执行任何操作,因为HouseEntity不拥有该关系。您需要了解这一点。 housePersonEntity字段仅用于查询和结果,而不用于插入和更新。