我们正在使用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
}
答案 0 :(得分:0)
问题在于代码在子代的声明上有/ Cascade,而b /尝试直接操作子代而不更新父引用。使用Cascade选项,删除HostConfiguration(包括两个InterfaceConfiguration)的用例如下:
em.remove(hc);
并修改HostConfiguration上的InterfaceConfigurations,如:
hc.setTrustedInterface(...);
hc.setUntrustedInterface(...);
entityManager.merge(hc);
如果您想管理子实体和父实体,请显式删除Cascade注释。