java - Hibernate 的删除方法给出 StaleStateException

标签 java hibernate hibernate-mapping

我正在尝试使用 Hibernate 的删除方法删除对象,但出现 StaleStateException 异常。我的要求是根据唯一键删除对象,因此我正在做类似的事情。

String queryString="from Destination destination "+
                                                   "where destination.destinationID = :destinationid";
    tx.begin();
                Query query= session.createQuery(queryString).setParameter("destinationid", destinationId, Hibernate.STRING);
               @SuppressWarnings("unchecked")
               List<Destination> list=query.list();
               Destination ds=list.get(0);
                 if(!list.isEmpty())
                  session.evict(ds);
                  session.delete(ds);

                  tx.commit();

因为我知道列表中只有一个元素(如果它不为空),所以只从列表中获取第一个元素(不确定这是否是一个好方法)

但是当我运行这个方法时,我可以在控制台中看到以下 sql 日志

Hibernate: 
    /* delete collection AirTransport.timeTable */ delete 
        from
            tr.TRANSPORTTIME 
        where
            TRANSPORTID=?
Hibernate: 
    /* delete collection AirTransport.timeTable */ delete 
        from
            tr.TRANSPORTTIME 
        where
            TRANSPORTID=?
Hibernate: 
    /* delete collection AirTransport.timeTable */ delete 
        from
            tr.TRANSPORTTIME 
        where
            TRANSPORTID=?
Hibernate: 
    /* delete collection RoadTransport.timeTable */ delete 
        from
            tr.TRANSPORTTIME 
        where
            TRANSPORTID=?
Hibernate: 
    /* delete collection TrainTransport.timeTable */ delete 
        from
            tr.TRANSPORTTIME 
        where
            TRANSPORTID=?
Hibernate: 
    /* delete AirTransport */ delete 
        from
            tr.TRANSPORT 
        where
            UUID=?
Hibernate: 
    /* delete AirTransport */ delete 
        from
            tr.TRANSPORT 
        where
            UUID=?
Hibernate: 
    /* delete AirTransport */ delete 
        from
            tr.TRANSPORT 
        where
            UUID=?
Hibernate: 
    /* delete RoadTransport */ delete 
        from
            tr.TRANSPORT 
        where
            UUID=?

并且比它的 throw

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:61)
 at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:46)

让我怀疑的一件事是,在我的运输表中,我有三个条目,只有一个用于航空运输,一个用于火车,最后一个用于公路,在 TransPortTime 表中,我有三个条目,每个条目用于每种运输类型,

我在所有三个传输类中使用 TransportTime 作为复合元素

<set name="timeTable" table="TRANSPORTTIME" lazy="true">
                        <key column="TRANSPORTID"/>
                        <composite-element
                                class="TransportTime">

                                <property name="deperatureTime" type="java.util.Date">
                                        <column name="DEPERATURETIME" />
                                </property>
                                <property name="arrivalTime" type="java.util.Date">
                                        <column name="ARRIVALTIME" />
                                </property>
                                <other properties>
                        </composite-element>

                </set>

我仍然无法弄清楚出了什么问题,所以尽管在社区中询问

<小时/>

只是添加一些额外的信息: 我在三个相应的 trabsport 类别的目标类别中有以下映射

<set name="airTransport" table="AIRTRANSPORT" inverse="true" lazy="true" cascade="save-update, delete">
        <key>
            <column name="DESTINATIONID" />
        </key>
        <one-to-many class="AirTransport" />
    </set>
    <set name="roadTransport" table="ROADTRANSPORT" inverse="true" lazy="true" cascade="save-update, delete">
        <key>
            <column name="DESTINATIONID" />
        </key>
        <one-to-many class="RoadTransport" />
    </set>
    <set name="trainTransport" table="TRAINTRANSPORT" inverse="true" lazy="true" cascade="save-update, delete">
        <key>
            <column name="DESTINATIONID" />
        </key>
        <one-to-many class="TrainTransport" />
    </set>

在我的公路运输/火车/航空运输中具有以下映射

<class name="AirTransport" table="TRANSPORT">
        <id name="uuid" type="java.lang.String">
            <column name="UUID" />
            <generator class="uuid"/>
        </id>
        <many-to-one name="destination" class="Destination" fetch="join">
            <column name="DESTINATIONID" />
        </many-to-one>
       <property mappings>
        <set name="timeTable" table="TRANSPORTTIME" lazy="true">
            <key column="TRANSPORTID"/>
            <composite-element
                class="TransportTime">
                <property mappings>
                </composite-element>

        </set>
    </class>

其他两个映射文件也相同 因此,当我从父类中删除这三个类的映射关联时,我的删除功能开始完美运行。

所以这意味着我在将 TimeTable 类映射为 Transport 类(航空/火车/公路运输类)内的组件时犯了根本错误

这方面的任何建议都会很有帮助

最佳答案

当版本号或时间戳检查失败时,会抛出 StaleStateException,表明 session 包含过时的数据(当使用带版本控制的长事务时)。如果我们尝试删除或更新不存在的行,也会发生这种情况。

请注意,此异常通常表明用户未能为类指定正确的未保存值策略!

http://www.dil.univ-mrs.fr/~massat/docs/hibernate-3.1/api/org/hibernate/StaleStateException.html

我的猜测是,您的行在这个长事务期间被更新。当它尝试提交删除时,它发现版本不同( session 中标记为删除的版本和数据库中的实际行),因此抛出 StaleStateException

此外,Query 类应该有一些名为 uniqueResult() 的方法,如果您确定每次执行它都会返回一个结果,它将返回一个对象结果。这将为您节省一些尝试获取列表部分的第 0 个索引的代码。

关于java - Hibernate 的删除方法给出 StaleStateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4723602/

相关文章:

java - 为什么一个程序会为我编译,而不是为另一个人编译?

java - hibernate实体中的必填字段

java - Hibernate SQlite映射类与内部类异常数据库文件被锁定(database is lock)

Hibernate @ManyToOne 和@OneToMany 获取数据作为列表(记录数)

mysql - Hibernate + MySQL 中的 bool 映射问题

java - 为什么在配置文件中定义类时需要@Entity注解

java - 如何使用java中的标签从一个for循环跳转到另一个for循环?

java - 如何处理大数组/列表

java - Hibernate SQL异常

java - JSP中获取Set的第一个元素