Hibernate:使用@Version获取StaleStateException

时间:2016-11-16 07:41:14

标签: hibernate

解释问题

请查看下面的代码,我正在使用@Version annonation并使用两个java类:一个用于保存Student实例,另一个用于更新同一个Student实例。我从实例本身提供Id值。在第一次更新时,学生姓名的值会更新,并且版本也会增加1,但如果它再次尝试更改学生姓名:我收到以下异常。请帮忙!!!

**Student.java**

package com.emb.hib;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Version;

@Entity
@Table(name = "STUDENTS")
public class Student {

    @Id
    @Column(name = "STUD_ID")
    private int studId;

    @Column(name = "STUD_NAME")
    private String StudName;

    @Version
    @Column(name = "VERSION", nullable = false, columnDefinition = "integer DEFAULT 0") 
    private long version;

    public Student(int studId, String studName) {
        super();
        this.studId = studId;
        StudName = studName;
    }

    public int getStudId() {
        return studId;
    }

    public void setStudId(int studId) {
        this.studId = studId;
    }

    public String getStudName() {
        return StudName;
    }

    public void setStudName(String studName) {
        StudName = studName;
    }

    public long getVersion() {
        return version;
    }

    public void setVersion(long version) {
        this.version = version;
    }

}

**StudentRecSave.java**

package com.emb.hib;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

public class StudentRecSave {

    public static void main(String[] args) {

        StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
                .configure("hibernate.cfg.xml").build();
        Metadata metadata = new MetadataSources(standardRegistry)
                .getMetadataBuilder().build();
        SessionFactory sessionFactory = metadata.getSessionFactoryBuilder()
                .build();
        Session session = sessionFactory.openSession();

        Student rukmini = new Student(1, "Rukmini");

        Transaction tx = session.beginTransaction();
        session.persist(rukmini);
        tx.commit();

        session.close();
        System.out.println("Student record saved");
    }

}

**StudentRecUpdate.java**

package com.emb.hib;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

public class StudentRecUpdate {

    public static void main(String[] args) {

        StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
                .configure("hibernate.cfg.xml").build();
        Metadata metadata = new MetadataSources(standardRegistry)
                .getMetadataBuilder().build();
        SessionFactory sessionFactory = metadata.getSessionFactoryBuilder()
                .build();
        Session session = sessionFactory.openSession();

        Student rukmini = new Student(1, "Rukmini Iyer");

        Transaction tx = session.beginTransaction();
        session.saveOrUpdate(rukmini);
        tx.commit();
        session.close();

        System.out.println("Student record updated");

    }

}



**hibernate.cfg.xml**

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM 
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.dialect">
            org.hibernate.dialect.MySQLDialect
        </property>
        <property name="hibernate.connection.driver_class">
            com.mysql.jdbc.Driver
        </property>

        <!-- Assume test is the database name -->
        <property name="hibernate.connection.url">
            jdbc:mysql://localhost/test
        </property>
        <!-- <property name="hibernate.connection.username">root</property> -->
        <!--<property name="hibernate.connection.password">root123</property> -->

        <property name="hbm2ddl.auto">update</property>
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        <property name="use_sql_comments">true</property>

        <!-- List of XML mapping files -->
        <mapping package="com.emb.hib" />
        <mapping class="com.emb.hib.Student" />

    </session-factory>
</hibernate-configuration>

控制台输出

Nov 16, 2016 12:42:12 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.0.5.Final}
Nov 16, 2016 12:42:12 PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
Nov 16, 2016 12:42:12 PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
Nov 16, 2016 12:42:12 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
Nov 16, 2016 12:42:12 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)
Nov 16, 2016 12:42:12 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost/test]
Nov 16, 2016 12:42:12 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {}
Nov 16, 2016 12:42:12 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Nov 16, 2016 12:42:12 PM org.hibernate.engine.jdbc.connections.internal.PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
Nov 16, 2016 12:42:13 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
Nov 16, 2016 12:42:13 PM org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl useContextualLobCreation
INFO: HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4
Nov 16, 2016 12:42:13 PM org.hibernate.tuple.PojoInstantiator <init>
INFO: HHH000182: No default (no-argument) constructor for class: com.emb.hib.Student (class must be instantiated by Interceptor)
Nov 16, 2016 12:42:13 PM org.hibernate.tuple.PojoInstantiator <init>
INFO: HHH000182: No default (no-argument) constructor for class: com.emb.hib.Person (class must be instantiated by Interceptor)
Nov 16, 2016 12:42:13 PM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000228: Running hbm2ddl schema update
Hibernate: 
    /* get current state com.emb.hib.Student */ select
        student_.STUD_ID,
        student_.STUD_NAME as STUD_NAM2_1_,
        student_.VERSION as VERSION3_1_ 
    from
        STUDENTS student_ 
    where
        student_.STUD_ID=?
Hibernate: 
    /* update
        com.emb.hib.Student */ update
            STUDENTS 
        set
            STUD_NAME=?,
            VERSION=? 
        where
            STUD_ID=? 
            and VERSION=?
Nov 16, 2016 12:42:13 PM org.hibernate.internal.SessionImpl$5 mapManagedFlushFailure
ERROR: HHH000346: Error during managed flush [Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1]
Exception in thread "main" org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
    at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:67)
    at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:54)
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:46)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3070)
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2949)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3329)
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:145)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:560)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:434)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:465)
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2963)
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2339)
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:146)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:230)
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
    at com.emb.hib.StudentRecUpdate.main(StudentRecUpdate.java:27)

0 个答案:

没有答案