java - 单线程中的 JPA 乐观锁异常
问题描述
我正在尝试使用 JPA 持久性类更新基本删除时间戳。这是代码:
public void delete(Document document, EntityManager em, SessionContext ctx)
throws MyException {
try {
ctx.getUserTransaction().begin();
DocumentDB documentDB = em.find(WDSDocument.class, document.getId());
if (documentDB != null) {
em.lock(documentDB, LockModeType.WRITE);
documentDB.setDeletedAt(new Timestamp(System.currentTimeMillis()));
em.merge(documentDB);
em.flush(); // OptimisticLockException raised here
}
ctx.getUserTransaction().commit();
if (log.isDebugEnabled()) log.debug("DELETED " + document.getId());
} catch (Exception e) {
ctx.getUserTransaction().rollback();
throw new MyException(Utils.getError("ERR9", new String[] { "" + document.getId(), e.getMessage() }),
e);
}
}
Id
与as相同的文档document
已存储在数据库中,我想更新单个字段。
该em.flush()
行引发了异常,好像另一个用户(线程)试图更新同一个对象,但在我的应用程序中并非如此。
我OptimisticLockException
在 JPA 中阅读过,并且我知道当同一个用户尝试连续两次更新对象而不首先刷新/提交到数据库时,可以引发它。
显然,每当我尝试更新documentDB
任何对象的删除时间戳时都会发生此错误,因此我想我的方法应该存在固有的错误,delete()
即双重更新对象本身。到目前为止,我无法正确排除故障。
已编辑
这是我的DocumentDB
课
@Entity
@Table(name = "DOCUMENTS", schema = "WP")
public class DocumentDB extends AbstractEntity {
private static final long serialVersionUID = -98765134L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID_DOCUMENT", nullable = false)
private int id;
@Column(name = "SOURCE")
private String source = null;
@Column(name = "CREATION_DATE")
private Date creationDate;
@Column(name = "TITLE")
private String title = null;
@Column(name = "AUTHOR")
private String author = null;
@Column(name = "URL")
private String url = null;
@Column(name = "DELETED_AT")
private Timestamp deletedAt = null;
@Override
public Integer getId() {
return id;
}
@Override
public void setId(int id) {
this.id = id;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Timestamp getDeletedAt() {
return deletedAt;
}
public void setDeletedAt(Timestamp deletedAt) {
this.deletedAt = deletedAt;
}
}
虽然它的抽象超类是:
@MappedSuperclass
public abstract class AbstractEntity implements Serializable {
private static final long serialVersionUID = -98765134L;
public abstract Integer getId();
public abstract void setId(int id);
/**
* Creator of the record
*/
@Column(name = "USER_CREATION", nullable = false)
protected String userCreation;
/**
* Timestamp of creation of the record
*/
@Column(name = "DATE_CREATION", nullable = false)
protected Timestamp dateCreation;
/**
* User of the last change of the record
*/
@Column(name = "USER_LAST_CHANGE", nullable = false)
protected String userLastChange;
/**
* Timestamp of the last change of the record
*/
@Column(name = "DATE_LAST_CHANGE", nullable = false)
protected Timestamp dateLastChange;
/**
* Progressive of the variation of the record:
* used in optimistic locking of entity manager
* to avoid conflicts in insert/update
*/
@Version
@Column(name = "PG_VER_REC", nullable = false)
protected int progressiveVariationRecord;
public String getUserCreation() {
return userCreation;
}
public void setUserCreation(String userCreation) {
this.userCreation = userCreation;
}
public Timestamp getDateCreation() {
return dateCreation;
}
public void setDateCreation(Timestamp dateCreation) {
this.dateCreation = dateCreation;
}
public String getUserLastChange() {
return userLastChange;
}
public void setUserLastChange(String userLastChange) {
this.userLastChange = userLastChange;
}
public Timestamp getDateLastChange() {
return dateLastChange;
}
public void setDateLastChange(Timestamp dateLastChange) {
this.dateLastChange = dateLastChange;
}
public int getProgressiveVariationRecord() {
return progressiveVariationRecord;
}
public void setProgressiveVariationRecord(int progressiveVariationRecord) {
this.progressiveVariationRecord = progressiveVariationRecord;
}
}
为了更好地理解这个问题,您能否提供一些关于接下来要执行的步骤的指导?
更新
到目前为止,我还没有找到问题的根本原因。我怀疑我的 EclipseLink JPA 实现在更新 for 循环中的实体时会做一些奇怪的事情。
不幸的是,目前我没有时间和资源来深入挖掘,我正在使用悲观锁定作为解决方法。希望以后能找到真正的问题。
解决方案
推荐阅读
- docker - docker pull 失败,出现 503
- networking - OSPF 区域拓扑
- regex - 如何使用 RegExp 查找大写字母?
- javascript - 如何优化以下 JavaScript 函数
- android - CameraX - 取消绑定预览用例时崩溃
- ios - 如何在 alamofire 5.0.2 版本中设置自定义超时
- sql - 如何使用 URL slug 在 Postgres 中执行查询?
- google-sheets - 如何在 Google 表格的 QUERY 中使用 TEXT
- ssl - 无法将自签名证书与 tokio-rustls 一起使用
- android - 检测操作系统版本,然后建议用户安装应用程序