Я пытаюсь обновить базовую метку времени удаления, используя класс сохраняемости 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
, что и document
уже хранится в БД, и я хотел бы обновить одно поле.
* em.flush()
строка вызывает исключение, как если бы другой пользователь (поток) пытался обновить этот же объект, но в моем приложении это не так.
Я читал о OptimisticLockException
в JPA иЯ понимаю, что это может быть вызвано, когда один и тот же пользователь пытается обновить объект два раза подряд без предварительной очистки / фиксации в БД.
Видимо, эта ошибка возникает всякий раз, когда я пытаюсь обновить удаление documentDB
временная метка для любого объекта, поэтому я предполагаю, что в моем методе delete()
, который дважды обновляет сам объект, должно быть что-то не так.До сих пор я не мог правильно ее устранить.
EDITED
Вот мой 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.
К сожалению, на данный момент у меня нет времени и ресурсов, чтобы копать глубже, и я использую пессимистическую блокировку в качестве обходного пути.Надеюсь найти реальную проблему когда-нибудь в будущем.