JPA - 无法更新实体

时间:2014-10-27 11:36:04

标签: hibernate jpa

我们正在使用Hibernate作为在Tomcat服务器中运行的提供程序的JPA项目。问题是当我尝试更新实体时,它不会发生并导致异常。 HostConfiguration是我想使用SystemDaoImpl类更新的实体。这里的HostConfiguration又将InterfaceConfiguration作为子实体。 HostConfiguration有2个InterfaceConfiguration(s) - 可信和不可信。我的目标是 (a)更新其中一个接口配置,即删除现有接口配置并替换为新接口配置 (b)删除所有接口配置的完整主机配置,然后添加一个新配置。我想知道我该怎么做?通过网络浏览多个论坛后,我尝试了各种方法/组合。下面的代码给了我这个例外 -

  

org.hibernate.ObjectDeletedException:删除的对象将是   通过级联重新保存(从关联中删除已删除的对象):   [com.cisco.cpm.ipep.system.InterfaceConfiguration#InterfaceConfiguration.IfConfigPKey [类型= TRUSTED,ip地址= / 7.7.20.18]]

感谢您的任何帮助,谢谢。

//SystemDaoImpl.java

public class SystemDaoImpl {

//code omiited
@Override

public void setHostConfig(HostConfiguration hostConf) {

       HostConfiguration hc = em.find(HostConfiguration.class, hostConf.getHostname());
       if(hc != null) {
       InterfaceConfiguration trusted = hc.getTrustedInterface();
       InterfaceConfiguration untrusted = hc.getUntrustedInterface();

       if(!hostConf.equals(hc) || !trusted.equals(hostConf.getTrustedInterface()) || !untrusted.equals(hostConf.getUntrustedInterface())) {
       log.info("removing the existing hostconf");
       em.remove(hc);   
       InterfaceConfiguration.IfConfigPKey tpkey = new InterfaceConfiguration.IfConfigPKey();                   
       tpkey.setType(Type.TRUSTED);
       tpkey.setIpAddress(trusted.getIpAddress());
       InterfaceConfiguration trusted1 = em.find(InterfaceConfiguration.class, tpkey);
       if(trusted1 != null) {
       em.remove(trusted1);
       }
       InterfaceConfiguration.IfConfigPKey upkey = new InterfaceConfiguration.IfConfigPKey();                   
       tpkey.setType(Type.UNTRUSTED);
       tpkey.setIpAddress(untrusted.getIpAddress());
       InterfaceConfiguration untrusted1 = em.find(InterfaceConfiguration.class, upkey);
       if(untrusted1 != null) {
       em.remove(untrusted1);
       }
       log.info("now adding the new hostconf: " + hostConf);
       em.merge(hostConf);
       } else {
       log.info("hostConf and existing hostConf are equal");
       }
       }

 //some code removed ...
       }

HostConfiguration.java

@Entity

@Table(name = "host_configurations")

@XmlRootElement(name = "host_configuration")

@XmlAccessorType(XmlAccessType.FIELD)

public class HostConfiguration implements Cloneable {
public enum HostType {

    PRIMARY, SECONDARY, SERVICE
  }



@Id

@XmlElement

private String hostname;

@XmlElement

private String peerHostname;

@Enumerated

@XmlElement

private HostType type    = HostType.PRIMARY;
 @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)

 @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)

 @JoinColumns({

        @JoinColumn(name = "trusted_interface_type", referencedColumnName = "type", nullable = false),
        @JoinColumn(name = "trusted_interface_ip_address", referencedColumnName = "ip_address", nullable = false) })

@XmlElement(name = "trusted_interface")

private InterfaceConfiguration  trustedInterface;

 @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)

 @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)

 @JoinColumns({

        @JoinColumn(name = "untrusted_interface_type", referencedColumnName = "type", nullable = false),

        @JoinColumn(name = "untrusted_interface_ip_address", referencedColumnName = "ip_address", nullable = false) })

 @XmlElement(name = "untrusted_interface")

 private InterfaceConfiguration    untrustedInterface;

 //code removed

}

InterfaceConfiguration.java

@Entity

@Table(name = "interface_configurations")

@IdClass(InterfaceConfiguration.IfConfigPKey.class)

@XmlAccessorType(XmlAccessType.FIELD)

public class InterfaceConfiguration implements Cloneable {
public enum Type {
 TRUSTED, UNTRUSTED
 }

 @Id

@Enumerated

@XmlElement

private Type type;

@Id

@Column(name = "ip_address")

@XmlElement(name = "ip_address")

@XmlJavaTypeAdapter(value = InetAddressXmlAdapter.class)

private InetAddress ipAddress;

@XmlElement

private Subnet netmask;

@Column(name = "vlan_native")

@XmlElement(name = "vlan_native")

private boolean vlanNative;

@XmlElement

@XmlJavaTypeAdapter(value = InetAddressXmlAdapter.class)

private InetAddress gateway;

@Column(name = "vlan_id")

@XmlElement(name = "vlan_id")

private int vlanId;

//code removed

}

1 个答案:

答案 0 :(得分:0)

问题在于代码在子代的声明上有/ Cascade,而b /尝试直接操作子代而不更新父引用。使用Cascade选项,删除HostConfiguration(包括两个InterfaceConfiguration)的用例如下:

em.remove(hc);  

并修改HostConfiguration上的InterfaceConfigurations,如:

hc.setTrustedInterface(...);
hc.setUntrustedInterface(...);
entityManager.merge(hc);

如果您想管理子实体和父实体,请显式删除Cascade注释。