尝试使用 OpenJPA 进行批量删除时出现 EntityExistsException
我有三个类:Location、MTFCC 和 BorderPoint。
Location 与 MTFCC 具有单向 @ManyToOne 关系,该关系仅用作查找表。没有定义级联。
Location 还有一个双向 @ManyToOne/@OneToMany 和 BorderPoint。由于我希望在删除位置时删除所有关联的 BorderPoint 对象,因此我在关系的位置一侧设置了cascadetype.ALL。
不幸的是,当我尝试删除某个位置时,会引发 EntityExistsException:
org.apache.openjpa.persistence.EntityExistsException: Cannot delete or update
a parent row: a foreign key constraint fails (`mapmaker`.`BORDERPOINT`,
CONSTRAINT `BORDERPOINT_ibfk_1` FOREIGN KEY (`LOCATIONID`) REFERENCES `LOCATION`
(`LOCATIONID`)) {prepstmnt 21576566 DELETE t0, t1 FROM LOCATION t0 INNER JOIN
MTFCC t1 ON t0.MTFCCID = t1.MTFCCID WHERE (t0.STATEFP = ? AND t1.MTFCCCODE = ?)
[params=?, ?]} [code=1451, state=23000]
[ERROR] FailedObject: DELETE t0, t1 FROM LOCATION t0 INNER JOIN MTFCC t1 ON
t0.MTFCCID = t1.MTFCCID WHERE (t0.STATEFP = ? AND t1.MTFCCCODE = ?)
[java.lang.String]
看起来它正在尝试删除关联的 MTFCC 对象,但我不希望发生这种情况。但是,我确实希望删除关联的 BorderPoint 对象。
这是代码(删减了一点):
@SuppressWarnings("unused")
@Entity
@Table(name="LOCATION")
@DetachedState(enabled=true)
public class Location implements Serializable, IsSerializable, Cloneable {
private Long id;
private String stateGeoId;
private MTFCC mtfcc;
private List<BorderPoint> borderPointList;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="LOCATIONID")
public Long getId() {
return id;
}
@ManyToOne
@JoinColumn(name="MTFCCID")
public MTFCC getMtfcc() {
return mtfcc;
}
@OneToMany(cascade = CascadeType.ALL, mappedBy = "location", fetch = FetchType.EAGER)
public List<BorderPoint> getBorderPointList() {
return borderPointList;
}
}
@Entity
@Table(name = "BORDERPOINT")
@DetachedState(enabled = true)
public class BorderPoint implements Serializable, IsSerializable {
private Long id;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="BORDERID")
public Long getId() {
return id;
}
@ManyToOne(targetEntity = Location.class)
@JoinColumn(name="LOCATIONID")
public Location getLocation() {
return location;
}
}
@Entity
@Table(name = "MTFCC")
public class MTFCC implements Serializable, IsSerializable {
private Long id;
private String mtfccCode;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "MTFCCID")
public Long getId() {
return id;
}
// etc
}
而且,为了更好地衡量,这里是删除代码:
@Override
@Transactional
public int removeByStateGeoIdAndMtfcc(String stateGeoId, String mtfccCode) throws RepositoryException {
EntityManager em = entityManagerFactory.createEntityManager();
String jpaQuery = "DELETE FROM Location L where L.stateFP = ?1 AND L.mtfcc.mtfccCode = ?2";
int affectedRows = 0;
Query query = em.createQuery(jpaQuery).setParameter(1, stateGeoId).setParameter(2, mtfccCode);
try {
em.getTransaction().begin();
affectedRows = query.executeUpdate();
em.getTransaction().commit();
} catch (Exception e) {
//log.debug("Exception: ", e);
throw new RepositoryException(e);
}
em.close();
return affectedRows;
}
希望我复制了所有相关部分......任何人都可以帮忙吗?
I have three classes: Location, MTFCC, and BorderPoint.
Location has a unidirectional @ManyToOne relationship with MTFCC, which is intended only as a Lookup table. No cascading is defined.
Location also has a bidirectional @ManyToOne/@OneToMany with BorderPoint. Since I want all associated BorderPoint objects to delete when I delete a Location, I set cascadetype.ALL on the Location side of the relationship.
Unfortunately, an EntityExistsException is being thrown when I attempt to delete a location:
org.apache.openjpa.persistence.EntityExistsException: Cannot delete or update
a parent row: a foreign key constraint fails (`mapmaker`.`BORDERPOINT`,
CONSTRAINT `BORDERPOINT_ibfk_1` FOREIGN KEY (`LOCATIONID`) REFERENCES `LOCATION`
(`LOCATIONID`)) {prepstmnt 21576566 DELETE t0, t1 FROM LOCATION t0 INNER JOIN
MTFCC t1 ON t0.MTFCCID = t1.MTFCCID WHERE (t0.STATEFP = ? AND t1.MTFCCCODE = ?)
[params=?, ?]} [code=1451, state=23000]
[ERROR] FailedObject: DELETE t0, t1 FROM LOCATION t0 INNER JOIN MTFCC t1 ON
t0.MTFCCID = t1.MTFCCID WHERE (t0.STATEFP = ? AND t1.MTFCCCODE = ?)
[java.lang.String]
It looks like it's attempting to delete the associated MTFCC object which I do NOT want to happen. I do, however, want the associated BorderPoint objects to be deleted.
Here is the code (chopped down a bit):
@SuppressWarnings("unused")
@Entity
@Table(name="LOCATION")
@DetachedState(enabled=true)
public class Location implements Serializable, IsSerializable, Cloneable {
private Long id;
private String stateGeoId;
private MTFCC mtfcc;
private List<BorderPoint> borderPointList;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="LOCATIONID")
public Long getId() {
return id;
}
@ManyToOne
@JoinColumn(name="MTFCCID")
public MTFCC getMtfcc() {
return mtfcc;
}
@OneToMany(cascade = CascadeType.ALL, mappedBy = "location", fetch = FetchType.EAGER)
public List<BorderPoint> getBorderPointList() {
return borderPointList;
}
}
@Entity
@Table(name = "BORDERPOINT")
@DetachedState(enabled = true)
public class BorderPoint implements Serializable, IsSerializable {
private Long id;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="BORDERID")
public Long getId() {
return id;
}
@ManyToOne(targetEntity = Location.class)
@JoinColumn(name="LOCATIONID")
public Location getLocation() {
return location;
}
}
@Entity
@Table(name = "MTFCC")
public class MTFCC implements Serializable, IsSerializable {
private Long id;
private String mtfccCode;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "MTFCCID")
public Long getId() {
return id;
}
// etc
}
And, for good measure, here is the deletion code:
@Override
@Transactional
public int removeByStateGeoIdAndMtfcc(String stateGeoId, String mtfccCode) throws RepositoryException {
EntityManager em = entityManagerFactory.createEntityManager();
String jpaQuery = "DELETE FROM Location L where L.stateFP = ?1 AND L.mtfcc.mtfccCode = ?2";
int affectedRows = 0;
Query query = em.createQuery(jpaQuery).setParameter(1, stateGeoId).setParameter(2, mtfccCode);
try {
em.getTransaction().begin();
affectedRows = query.executeUpdate();
em.getTransaction().commit();
} catch (Exception e) {
//log.debug("Exception: ", e);
throw new RepositoryException(e);
}
em.close();
return affectedRows;
}
Hopefully I copied all relevant parts... can anyone assist?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您没有正确阅读错误消息。它说由于
BorderPoint
和Location
之间的外键约束,禁止删除。如果您使用
em.remove(location)
删除您的Location
,级联删除将会起作用。使用像您这样的删除查询不会在删除位置之前自动删除BorderPoint
。使用
em.remove
加载它们并删除它们,或者在删除BorderPoint
之前执行其他删除查询。You aren't reading the error message correctly. It says that the deletion is forbidden because of the foreign key constraint between
BorderPoint
andLocation
.The cascade delete would work if you used
em.remove(location)
to delete yourLocation
. Using a delete query like you're doing won't automagically delete theBorderPoint
s before deleting the location.Either load them and remove them using
em.remove
, or execute other delete queries before to delete theBorderPoint
s.