尝试使用 OpenJPA 进行批量删除时出现 EntityExistsException

发布于 2024-11-19 09:24:11 字数 3248 浏览 1 评论 0原文

我有三个类: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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

云胡 2024-11-26 09:24:11

您没有正确阅读错误消息。它说由于 BorderPointLocation 之间的外键约束,禁止删除。

如果您使用 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 and Location.

The cascade delete would work if you used em.remove(location) to delete your Location. Using a delete query like you're doing won't automagically delete the BorderPoints before deleting the location.

Either load them and remove them using em.remove, or execute other delete queries before to delete the BorderPoints.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文