我正在从具有与同一实体(表示节点层次结构)的一对多关系的表中删除实体。如果我将xincoCoreNodeId关系设为级联,那么它可以正常工作,但我不想在实际应用程序中使用它。
我不想删除删除其父级的叶子。有没有办法在运行时修改此关系或禁用约束,以便我可以删除整个表内容而不会产生约束抱怨?
package com.bluecubs.xinco.core.server.persistence;
import com.bluecubs.xinco.core.server.AuditedEntityListener;
import com.bluecubs.xinco.core.server.XincoAuditedObject;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.eclipse.persistence.annotations.PrivateOwned;
/**
*
* @author Javier A. Ortiz Bultrón <javier.ortiz.78@gmail.com>
*/
@Entity
@Table(name = "xinco_core_node")
@EntityListeners(AuditedEntityListener.class)
@NamedQueries({
@NamedQuery(name = "XincoCoreNode.findAll", query = "SELECT x FROM XincoCoreNode x"),
@NamedQuery(name = "XincoCoreNode.findById", query = "SELECT x FROM XincoCoreNode x WHERE x.id = :id"),
@NamedQuery(name = "XincoCoreNode.findByDesignation", query = "SELECT x FROM XincoCoreNode x WHERE x.designation = :designation"),
@NamedQuery(name = "XincoCoreNode.findByStatusNumber", query = "SELECT x FROM XincoCoreNode x WHERE x.statusNumber = :statusNumber")})
public class XincoCoreNode extends XincoAuditedObject implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "id", nullable = false)
private Integer id;
@Basic(optional = false)
@Column(name = "designation", nullable = false, length = 255)
private String designation;
@Basic(optional = false)
@Column(name = "status_number", nullable = false)
private int statusNumber;
@JoinColumn(name = "xinco_core_language_id", referencedColumnName = "id", nullable = false)
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private XincoCoreLanguage xincoCoreLanguageId;
@OneToMany(cascade = CascadeType.PERSIST, mappedBy = "xincoCoreNodeId", fetch = FetchType.LAZY)
private List<XincoCoreNode> xincoCoreNodeList;
@JoinColumn(name = "xinco_core_node_id", referencedColumnName = "id")
@PrivateOwned
@ManyToOne(fetch = FetchType.LAZY)
private XincoCoreNode xincoCoreNodeId;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "xincoCoreNodeId", fetch = FetchType.LAZY)
private List<XincoCoreAce> xincoCoreAceList;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "xincoCoreNodeId", fetch = FetchType.LAZY)
private List<XincoCoreData> xincoCoreDataList;
public XincoCoreNode() {
}
public XincoCoreNode(Integer id) {
this.id = id;
}
public XincoCoreNode(Integer id, String designation, int statusNumber) {
this.id = id;
this.designation = designation;
this.statusNumber = statusNumber;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public int getStatusNumber() {
return statusNumber;
}
public void setStatusNumber(int statusNumber) {
this.statusNumber = statusNumber;
}
public XincoCoreLanguage getXincoCoreLanguageId() {
return xincoCoreLanguageId;
}
public void setXincoCoreLanguageId(XincoCoreLanguage xincoCoreLanguageId) {
this.xincoCoreLanguageId = xincoCoreLanguageId;
}
public List<XincoCoreNode> getXincoCoreNodeList() {
return xincoCoreNodeList;
}
public void setXincoCoreNodeList(List<XincoCoreNode> xincoCoreNodeList) {
this.xincoCoreNodeList = xincoCoreNodeList;
}
public XincoCoreNode getXincoCoreNodeId() {
return xincoCoreNodeId;
}
public void setXincoCoreNodeId(XincoCoreNode xincoCoreNodeId) {
this.xincoCoreNodeId = xincoCoreNodeId;
}
public List<XincoCoreAce> getXincoCoreAceList() {
return xincoCoreAceList;
}
public void setXincoCoreAceList(List<XincoCoreAce> xincoCoreAceList) {
this.xincoCoreAceList = xincoCoreAceList;
}
public List<XincoCoreData> getXincoCoreDataList() {
return xincoCoreDataList;
}
public void setXincoCoreDataList(List<XincoCoreData> xincoCoreDataList) {
this.xincoCoreDataList = xincoCoreDataList;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof XincoCoreNode)) {
return false;
}
XincoCoreNode other = (XincoCoreNode) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "com.bluecubs.xinco.core.server.persistence.XincoCoreNode[id=" + id + "]";
}
}
答案 0 :(得分:0)
如果您正在使用Hibernate,则可以使用它对batch processing的支持来有效地删除表中的许多行。基本上,查询从HQL转换为SQL并直接针对数据库运行。但是,这种方法存在局限性。例如,如果要保留对任何受影响对象的引用,则不会更新内存中状态。
我不知道JPA本身是否支持批处理。可能不是。但是如果你期望影响很多行(数百或数千),那么无论如何,这是ORM不是真正适合工作的那种情况之一。在直接SQL或存储过程中执行它可能更有意义。无论哪种方式,您都可以隔离数据访问对象中的代码,以便高级业务逻辑无需关心操作的实现方式。
答案 1 :(得分:0)
我结束了用Java处理这个特殊情况。
@Override
public void clearTable() {
try {
/**
* All nodes are linked except the root. So we need to start deleting the leaves first.
*/
while (new XincoCoreNodeJpaController().findXincoCoreNodeEntities().size() > 0) {
for (com.bluecubs.xinco.core.server.persistence.XincoCoreNode xcn : getLeaves()) {
new XincoCoreNodeJpaController().destroy(xcn.getId());
}
}
} catch (XincoException ex) {
Logger.getLogger(XincoCoreNodeServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
private Vector<com.bluecubs.xinco.core.server.persistence.XincoCoreNode> getLeaves() throws XincoException {
Vector<com.bluecubs.xinco.core.server.persistence.XincoCoreNode> leaves =
new Vector<com.bluecubs.xinco.core.server.persistence.XincoCoreNode>();
result = XincoDBManager.protectedCreatedQuery("select x from XincoCoreNode x " +
"where x.id not in (select y.xincoCoreNodeId.id from XincoCoreNode y " +
"where y.xincoCoreNodeId is not null)",null,true);
if (result.size() == 0) {
//Check if the root is there
for (Object o : new XincoCoreNodeJpaController().findXincoCoreNodeEntities()) {
leaves.add((com.bluecubs.xinco.core.server.persistence.XincoCoreNode) o);
}
}
for (Object o : result) {
leaves.add((com.bluecubs.xinco.core.server.persistence.XincoCoreNode) o);
}
return leaves;
}