Java JPA在运行时删除约束
我正在从表中删除实体,该表与表示节点层次结构的同一实体具有一对多关系。如果我将xincoCoreNodeId关系设置为级联,那么所有这些都可以工作,但我不希望在实际应用程序中这样做 我不想删除一个叶子删除它的父对象。有没有一种方法可以在运行时修改此关系或禁用约束,这样我就可以删除整个表内容,而不会收到约束投诉Java JPA在运行时删除约束,java,jpa,Java,Jpa,我正在从表中删除实体,该表与表示节点层次结构的同一实体具有一对多关系。如果我将xincoCoreNodeId关系设置为级联,那么所有这些都可以工作,但我不希望在实际应用程序中这样做 我不想删除一个叶子删除它的父对象。有没有一种方法可以在运行时修改此关系或禁用约束,这样我就可以删除整个表内容,而不会收到约束投诉 package com.bluecubs.xinco.core.server.persistence; import com.bluecubs.xinco.core.server
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 + "]";
}
}
如果您使用的是Hibernate,那么可以使用它对的支持高效地删除表中的许多行。基本上,查询从HQL转换为SQL,并直接针对数据库运行。不过,这种方法也有局限性。例如,如果您持有对任何受影响对象的引用,则不会更新内存中的状态
我不知道JPA本身是否支持批处理。可能不会。但是,如果您希望影响数百行或数千行,那么无论如何,ORM并不是这项工作的正确工具。在纯SQL或存储过程中执行此操作可能更有意义。无论哪种方式,您都可以隔离数据访问对象中的代码,这样高级业务逻辑就不必关心操作是如何实现的。我最后用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;
}
如果不想将删除从leaf级联到父级,请不要像这样级联。事实上,我并不真正明白这个问题。在哪种情况下会出现约束冲突?我使用Eclipselink是因为我在Hibernate中发现了一些问题。好的,所以假设Eclipselink不支持本机批处理,我建议使用SQL选项。我试图避免使用SQL,因为目标数据库可以是JPA实现支持的任何东西。我将此视为例外,并以特殊的方式处理它。请参阅下面的工作代码。JpaController类是由Netbeans工具从main post中的实体类生成的。