我试图使用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=?
而不是投掷
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)
让我怀疑的一件事是,在我的Transport表中,我有三个条目,一个用于AirTransport一个用于Train,最后一个用于Road,在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>
并且在我的RoadTransport / Train / Air Transport中有以下映射
<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类(Air / Train / Road Transport类)中的组件时基本上是错误的
这方面的任何建议都会有所帮助
答案 0 :(得分:3)
当版本号或时间戳检查失败时抛出StaleStateException,表明Session包含过时数据(当使用带有版本控制的长事务时)。如果我们尝试删除或更新不存在的行,也会发生这种情况。
请注意,此异常通常表示用户未能为类指定正确的未保存值策略!
http://www.dil.univ-mrs.fr/~massat/docs/hibernate-3.1/api/org/hibernate/StaleStateException.html
我的猜测是,您的行在此长事务期间会更新。当它尝试提交删除时,它会看到版本不同(会话中标记为删除的版本和db中的实际行),因此抛出StaleStateException
此外,Query类应该有一个名为uniqueResult()
的方法,如果你确定每次执行它都会返回一个结果,它将返回一个对象结果。这样可以在尝试获取List部分的第0个索引时节省一些代码。
答案 1 :(得分:1)
您的代码(至少)有两种错误:
isEmpty()
。否则,您将面临异常风险evict()
行还要确保没有数据库触发器篡改返回的行数。