2009-12-14 55 views
0

我從表中刪除具有與同一個實體(代表節點層次結構)的一對多關係的實體。如果我使xincoCoreNodeId關係成爲級聯,但它並不是真正的應用程序。JPA在運行時刪除約束條件

我不想刪除刪除其父項的葉。有沒有辦法在運行時修改這種關係或禁用約束,這樣我就可以刪除整個表內容而不會收到約束條件的抱怨?

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 <[email protected]> 
*/ 
@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

如果您不想級聯刪除葉子到父級,請不要像級聯級聯。我其實並沒有真正解決問題。在這種情況下,你是否受到約束違規? – 2009-12-14 18:28:04

回答

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; 
} 
+0

JpaController類由主帖子中Entity類的Netbeans工具生成。 – javydreamercsw 2009-12-17 15:10:39

0

如果您正在使用Hibernate,你可以用它支持batch processing到表中的有效刪除多行。基本上,查詢從HQL轉換爲SQL並直接在數據庫上運行。不過,這種方法存在侷限性。例如,如果您持有對任何受影響對象的引用,則內存中狀態將不會更新。

我不知道JPA本身是否支持批處理。可能不會。但是,如果您希望影響很多行(數百或數千),那麼這就是ORM不是真正適合工作的正確工具的情況之一。在直接SQL或者存儲過程中執行它可能更有意義。無論哪種方式,您都可以將數據訪問對象內的代碼隔離開來,以便高級業務邏輯不需要關心操作如何實現。

+0

由於我在Hibernate中發現的一些問題,我正在使用Eclipselink。 – javydreamercsw 2009-12-16 15:31:58

+0

好吧,所以假設Eclipselink本身不支持批處理,我建議使用SQL選項。 – 2009-12-17 14:29:39

+0

我試圖避免SQL,因爲目標數據庫可以是JPA實現支持的任何東西。我將此視爲例外,並以特殊方式處理。請參閱以下工作代碼。 – javydreamercsw 2009-12-17 15:09:09