首先要清除一些事情:
HL7GeneralCode(父级)和HL7Address(子级)之间存在双向关联。如果HL7GeneralCode.addresses是“反”面(mappedBy),那么为什么拥有方HL7Address.use具有可插入/可更新的false?拥有方应控制此关联,因此您应删除insertable / updatable = false标志。
从父级到子级级联总是有意义的,而不是相反。但是在您的用例中,您尝试保留子项,并自动也保留父项。这就是为什么CASCADE.ALL在多对一末端没有意义的原因。
使用双向关联时,必须强制设置双方:
HL7Address addr = new HL7Address(); HL7GeneralCode pre = new HL7GeneralCode(); ... pre.getAddresses().add(addr); addr.setUse(pre);
持久操作旨在插入瞬态实体,而不要合并它们或重新附加实体。这意味着在您调用服务方法时,HL7Address和HL7GeneralCode都是新实体。如果您已经保存了具有相同ID的HL7GeneralCode,则将获得主键约束冲突异常。
如果HL7GeneralCode可能存在,则应从db获取它。
HL7GeneralCode pre = em.find(HL7GeneralCode, pk); HL7Address addr = new HL7Address(); if(pre != null) { pre = new HL7GeneralCode(); em.persist(pre); } pre.getAddresses().add(addr); addr.setUse(pre); em.persist(addr);更新
HL7Address地址不会覆盖equals / hashCode,因此将应用默认对象相同的引用检查规则。这将确保我们可以从pre.addresses列表中添加/删除地址。万一以后改变主意,请确保正确实现equals和hashCode。
尽管与您的问题无关,但您可能希望使用getter / setter而不是将字段公开。这样可以提供更好的封装,并且可以避免将setter与公共领域的访问权混在一起。
savehl7Address方法:
@Override public void savehl7Address(HL7Address addr) { HL7GeneralCode pre = addr.use(); if(pre != null && pre.getId()==null){ //HL7GeneralCode is not persistent. We don't support that throw new IllegalStateException("Cannot persist an adress using a non persistent HL7GeneralCode");//In case you'd want to support it//pre = em.find(HL7GeneralCode, pre.getId()); } //Merge the pre without any address info //This will ensure we only reattach the pre without triggering the address //transitive persistence by reachability addr.setUse(null); pre.getAddresses().remove(addr); pre = em.merge(pre); //Now set the pre to the address and vice-versa addr.setUse(pre); pre.getAddresses().add(addr); if ((Integer)addr.getId() == null) { System.out.println("[[[[[[[[[[[[ about to persist address ]]]]]]]]]]]]]]]]]]]]"); em.persist(addr); } else { System.out.println("]]]]]]]]]]]]]]]]]] about to merge address [[[[[[[[[[[[[[[[[[[[["); addr = em.merge(addr); }}


