我正在尝试使用 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/