JPA在运行时删除约束

时间:2009-12-14 15:40:57

标签: java jpa

我正在从具有与同一实体(表示节点层次结构)的一对多关系的表中删除实体。如果我将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 + "]";
    }
}

2 个答案:

答案 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;
}