Я использую hibernate, и я хотел обновить запись в моей базе данных. Однако всякий раз, когда я вызываю этот метод, я получаю знаменитое OptimisticLockException . Почему это исключение выбрасывается в моем случае? Как правильно обновить строку в базе данных?
Примечание : я запускаю этот метод только один раз. Итак, я предполагаю, что только один поток пытается обновить запись за раз.
Разделение объекта
@Entity
public class Section {
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(
name = "UUID",
strategy = "org.hibernate.id.UUIDGenerator",
parameters = {
@Parameter(
name = "uuid_gen_strategy_class",
value = "org.hibernate.id.uuid.CustomVersionOneStrategy"
)
}
)
private UUID id;
private String name;
private int type;
private int status;
@CreationTimestamp
private Date creationDate;
public Section(){
setStatus(Status.INACTIVE);
}
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getType() {
return type;
}
public void setType(Type type) {
switch (type){
case TOPIC:
this.type = 0;
break;
case QUESTION:
this.type = 1;
}
}
public void setStatus(Status status) {
switch (status){
case INACTIVE:
this.status = 0;
break;
case ACTIVE:
this.status = 1;
break;
case DELETED:
this.status = 2;
break;
}
}
public int getStatus() {
return status;
}
public Date getCreationDate() {
return creationDate;
}
public enum Status{
ACTIVE, INACTIVE, DELETED
}
public enum Type{
TOPIC, QUESTION;
public static int valueOf(Type type){
int value = -1;
switch (type){
case TOPIC:
value = 0;
break;
case QUESTION:
value = 1;
}
return value;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Section section = (Section) o;
return id == section.id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public String toString() {
return "Section{" +
"id=" + id +
", name='" + name + '\'' +
", type=" + type +
", status=" + status +
", creationDate=" + creationDate +
'}';
}
}
Метод обновления
@Test
public void updateTest(){
List<Section> sections = sectionDataAccessService.getQuestionSections(); // db call using hibernate
Session session = null;
StandardServiceRegistry sr = new StandardServiceRegistryBuilder().applySettings(configuration().getProperties()).build();
SessionFactory sessionFactory = configuration().buildSessionFactory(sr);
try {
session = sessionFactory.openSession();
session.beginTransaction();
Section section = sections.get(0);
// update goes here
section.setName("updated");
session.update(section);
// Committing The Transactions To The Database
session.getTransaction().commit();
System.out.println("............. section has been updated ................");
} catch(Exception sqlException) {
if(null != session.getTransaction()) {
System.out.println("\n.......Transaction Is Being Rolled Back.......");
session.getTransaction().rollback();
}
sqlException.printStackTrace();
} finally {
if(session != null) {
session.close();
}
}
}
sectionDataAccessService.getQuestionSections ( )
@Override
public List<Section> getQuestionSections() {
String query = "from Section where type = 1";
List<Section> list = null;
try {
list = hibernateAdapter.getList(query, true);
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
hibernateAdapter.getList ()
List<T> result = null;
StandardServiceRegistry sr = (new StandardServiceRegistryBuilder()).applySettings(this.configuration.getProperties()).build();
SessionFactory sessionFactory = this.configuration.buildSessionFactory(sr);
Session session = sessionFactory.openSession();
session.beginTransaction();
Query query = session.createQuery(hql);
query.setCacheable(isCacheables);
result = query.list();
session.getTransaction().commit();
session.close();
return result;
OptimisticLockException
javax.persistence.OptimisticLockException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.hassan.shammah.models.base.Section#c0a80069-706d-11b3-8170-6d61f49d0000]
at org.hibernate.internal.ExceptionConverterImpl.wrapStaleStateException(ExceptionConverterImpl.java:226)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:93)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1348)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:435)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3221)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2389)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
at com.hassan.shamah.data.service.relational.impl.SectionDataAccessImplTest.updateTest(SectionDataAccessImplTest.java:90)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[DEBUG] 2020-02-23 19:53:37.058 [main] TransactionImpl - rollback() called on an inactive transaction
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.hassan.shammah.models.base.Section#c0a80069-706d-11b3-8170-6d61f49d0000]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2574)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3420)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3283)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3695)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:149)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478)
at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:348)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:108)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1344)
... 34 more
ОБНОВЛЕНИЕ
Я включил статистику sessionFactory, чтобы получить представление о причине исключения. Я снова запустил свой код после включения статистики, я что-то получил .. Я вижу, что statistics.connectCount = 2, как показано на этом рисунке sessionFactory stats Я не уверен, почему это так, и это проблема или нет.