2009-12-14 3 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

Если вы не хотите, чтобы каскад удалялся из листьев в родительский, не каскадируйте его так же, как и вы. На самом деле я действительно не нахожу проблему. В этом случае у вас возникают нарушения ограничений? –

ответ

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 генерируются инструментами Netbeans из класса Entity в главном сообщении. – javydreamercsw

0

Если вы используете спящий режим, вы можете использовать свою поддержку batch processing эффективно удалить большое количество строк в таблице. В принципе, запрос переводится с HQL на SQL и напрямую работает с базой данных. Тем не менее, существуют ограничения с этим подходом. Например, состояние в памяти не будет обновляться, если вы держите ссылки на любой из затронутых объектов.

Я не знаю, поддерживает ли JPA пакетную обработку. Возможно нет. Но если вы планируете воздействовать на множество строк (сотни или тысячи), то это один из тех случаев, когда ORM на самом деле не является подходящим инструментом для работы. Это может иметь смысл сделать это в прямом SQL или, возможно, в хранимой процедуре. В любом случае вы можете изолировать код внутри объекта доступа к данным, чтобы бизнес-логика высокого уровня не заботилась о том, как выполняется эта операция.

+0

Я использую Eclipselink из-за некоторых проблем, которые я нашел с Hibernate. – javydreamercsw

+0

ОК, поэтому, предполагая, что Eclipselink не поддерживает пакетную обработку изначально, я бы порекомендовал переход с помощью опции SQL. –

+0

Я пытаюсь избежать SQL, поскольку целевая база данных может быть всякой поддержкой JPA. Я рассматривал это как исключение и обрабатывал его особым образом. См. Рабочий код ниже. – javydreamercsw

Смежные вопросы