hibernate: почему session.update () создает исключение OptimisticLockException? - PullRequest
0 голосов
/ 23 февраля 2020

Я использую 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 Я не уверен, почему это так, и это проблема или нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...