Please help me with this since I have ran out of ideas ...
We are using Spring's HibernateDaoSupport class to write our Hibernate DAO's.
We are getting StaleStateException when deleting "father" objects.
The operation is however successful since the order and the items are deleted from the database ....
I have created tests and can notice that if the number of orders are <= 17 the exception is not thrown.
The exception seems NOT to be related to any specific kind of data since when I moved the "test" window from
items 1..17 to items 5..21 it worked but 1..18 failed. I.e. item 18 is not responsible.
Merely the fact that we have 18 or more items in the order.
Note: Session and transaction handling is left over to Spring.
Hibernate: 3.2.7
Spring: 2.5.6
Java code:
Code:
public void remove(SharesEmissionOrder emissionOrder) {
getHibernateTemplate().delete(emissionOrder);
}
HBM code:
Code:
<class name="com.acme.bo.SharesEmissionOrder">
<id name="id">
<generator class="identity" />
</id>
<property name="year" not-null="true"/>
<property name="quarter" not-null="true"/>
<set name="stockBookHistoryItems" lazy="false" cascade="all">
<key column="emissionOrder"/>
<one-to-many class="com.tellpoker.bo.StockBookHistoryItem" />
</set>
<property name="sharesEmitted" not-null="true"/>
<property name="shareUnitsTotal" not-null="true"/>
<property name="numPlayers" not-null="true"/>
<property name="createdAt" type="timestamp" not-null="true"/>
<property name="executedAt" type="timestamp" not-null="false"/>
<many-to-one name="executedBy" not-null="false"/>
<property name="executedFromIpAddress" column="ipAddress" />
</class>
<class name="com.acme.bo.StockBookHistoryItem" table="StockBook">
<id name="id">
<generator class="identity" />
</id>
<many-to-one name="user" not-null="true" lazy="false" />
<property name="correspondingYear" not-null="false"/>
<property name="correspondingQuarter" not-null="false"/>
<property name="ownShareUnits" not-null="false"/>
<property name="firstLineShareUnits" not-null="false"/>
<property name="extraShareUnits" not-null="false"/>
<property name="totalShareUnits" not-null="false"/>
<property name="shares" not-null="true"/>
<property name="createdAt" type="timestamp" not-null="true"/>
<property name="deliveredAt" type="timestamp" not-null="false"/>
</class>
Java code:
Code:
/**
* Holds a batch information for all shares emissions that should
* be executed at a given time (quarterly).
*/
public class SharesEmissionOrder {
private Date createdAt = new Date();
private Date executedAt;
private User executedBy;
private String executedFromIpAddress;
private long id;
private int numPlayers;
private int quarter;
private int sharesEmitted;
private int shareUnitsTotal;
private Collection<StockBookHistoryItem> stockBookHistoryItems = new HashSet<StockBookHistoryItem>();
private int year;
public Date getCreatedAt() {
return createdAt;
}
public Date getExecutedAt() {
return executedAt;
}
public User getExecutedBy() {
return executedBy;
}
public String getExecutedFromIpAddress() {
return executedFromIpAddress;
}
public long getId() {
return id;
}
public int getNumPlayers() {
return numPlayers;
}
public int getQuarter() {
return quarter;
}
public int getSharesEmitted() {
return sharesEmitted;
}
public int getShareUnitsTotal() {
return shareUnitsTotal;
}
public Collection<StockBookHistoryItem> getStockBookHistoryItems() {
return stockBookHistoryItems;
}
public int getYear() {
return year;
}
public boolean isExecuted() {
return getExecutedAt() != null;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public void setExecutedAt(Date executedAt) {
this.executedAt = executedAt;
}
public void setExecutedBy(User executedBy) {
this.executedBy = executedBy;
}
public void setExecutedFromIpAddress(String executedFromIpAddress) {
this.executedFromIpAddress = executedFromIpAddress;
}
/**
* For Hibernate.
*/
@SuppressWarnings("unused")
private void setId(long id) {
this.id = id;
}
public void setNumPlayers(int numPlayers) {
this.numPlayers = numPlayers;
}
public void setQuarter(int quarter) {
this.quarter = quarter;
}
public void setSharesEmitted(int stocksEmitted) {
this.sharesEmitted = stocksEmitted;
}
public void setShareUnitsTotal(int shareUnitsTotal) {
this.shareUnitsTotal = shareUnitsTotal;
}
public void setStockBookHistoryItems(Collection<StockBookHistoryItem> items) {
stockBookHistoryItems = items;
}
public void setYear(int year) {
this.year = year;
}
}
/**
* Represents a piece of information of emitted shares to a specific User.
* Aggregate all instances of this class to get a full view on who owns shares,
* and how many.
*/
public class StockBookHistoryItem {
private int correspondingQuarter;
private int correspondingYear;
private Date createdAt = new Date();
private Date deliveredAt;
private int extraShareUnits;
private int firstLineShareUnits;
private long id;
private int ownShareUnits;
private int shares;
private int totalShareUnits;
private User user;
public StockBookHistoryItem() {}
public StockBookHistoryItem(ShareUnitsHolder shareUnits) {
this.user = shareUnits.getUser();
this.correspondingYear = shareUnits.getYear();
this.correspondingQuarter = shareUnits.getQuarter();
this.ownShareUnits = shareUnits.getOwnPlaySU();
this.firstLineShareUnits = shareUnits.getFromFirstLine();
this.extraShareUnits = shareUnits.getFromExtras();
}
public StockBookHistoryItem(User user, int correspondingYear, int correspondingQuarter, int ownShareUnits, int firstLineShareUnits, int extraShareUnits, int totalShareUnits, int shares) {
this.user = user;
this.correspondingYear = correspondingYear;
this.correspondingQuarter = correspondingQuarter;
this.ownShareUnits = ownShareUnits;
this.firstLineShareUnits = firstLineShareUnits;
this.extraShareUnits = extraShareUnits;
this.totalShareUnits = totalShareUnits;
this.shares = shares;
}
public String getCorrespondingYearAndQuarter() {
return correspondingYear + " - " + correspondingQuarter;
}
public int getCorrespondingQuarter() {
return correspondingQuarter;
}
public int getCorrespondingYear() {
return correspondingYear;
}
public Date getCreatedAt() {
return createdAt;
}
public Date getDeliveredAt() {
return deliveredAt;
}
public int getExtraShareUnits() {
return extraShareUnits;
}
public int getFirstLineShareUnits() {
return firstLineShareUnits;
}
public long getId() {
return id;
}
public int getOwnShareUnits() {
return ownShareUnits;
}
public int getShares() {
return shares;
}
public int getTotalItemShareUnits() {
return getOwnShareUnits() + getFirstLineShareUnits() + getExtraShareUnits();
}
public int getTotalShareUnits() {
return totalShareUnits;
}
public User getUser() {
return user;
}
public boolean isSpecialEmission() {
return getTotalItemShareUnits() == 0;
}
public void setCorrespondingQuarter(int correspondingQuarter) {
this.correspondingQuarter = correspondingQuarter;
}
public void setCorrespondingYear(int correspondingYear) {
this.correspondingYear = correspondingYear;
}
public void setCreatedAt(Date occuredAt) {
this.createdAt = occuredAt;
}
public void setDeliveredAt(Date deliveredAt) {
this.deliveredAt = deliveredAt;
}
public void setExtraShareUnits(int extraShareUnits) {
this.extraShareUnits = extraShareUnits;
}
public void setFirstLineShareUnits(int firstLineShareUnits) {
this.firstLineShareUnits = firstLineShareUnits;
}
/**
* For Hibernate.
*/
@SuppressWarnings("unused")
private void setId(long id) {
this.id = id;
}
public void setOwnShareUnits(int shareUnits) {
this.ownShareUnits = shareUnits;
}
public void setShares(int shares) {
this.shares = shares;
}
public void setTotalShareUnits(int totalShareUnits) {
this.totalShareUnits = totalShareUnits;
}
public void setUser(User user) {
this.user = user;
}
}