Hi there,
we are using Hibernate in a stateless Session EJB which is called the DBConnector. Each DB activity is wrapped in a business method of this EJB. For example the update Method (see below). The EJB has a member sessionFactory which provides the openSession for each call (see //1). The AutoCommit of the Session is explicitly set to false (see //2). The transferObject given to the EJBs update Method is updated (see //3), the session flushed (see //4) and then closed (see //5).
The Database is connected via the BEAs ConnectionPool using JNDI Lookup.
You may ask for the Transaction. The Transaction is handled by the EJB Container in our Environment.
The Problem is:
In most cases the update is working perfect. But sometimes - i know it sounds crazy - there occurs the HibernateException: SQL insert, update or delete failed (row not found). It is assured that no other process or user is concurrently deleting this record. The record does exist, because it's been read via the DBConnector before in the same transaction (read method is just the same as update, but - of course - using openSession.find(...)). And after the transaction's rollback it is still there!
I searched the forums and all the web. Nothing that really solved the Problem.
I tried to do the same in a TestEJB. I did 40.000 updates on the Database, but could not simulate this ugly situation. Does anybody know a solution?
By the way: Is flush invoking a asynchronous Task that is doing the "Flush-Job", or is flush waiting for its completion?
TIA,
Timon.
PS: YES, i will be doing tests with the newest Version (2.1.6) the next days.
Hibernate version:
2.1.3
Mapping documents:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<meta attribute="extends">TransferObject</meta>
<class name="de.kreditwerk.diamant.connectors.diamantdb.model.Codierung" schema="DIAMANT" table="CODIERUNG">
<id column="OID" name="oid" type="long">
<meta attribute="scope-set">protected</meta>
<generator class="sequence">
<param name="sequence">CODIERUNG_SEQ</param>
</generator>
</id>
<property column="VORGANGSID" length="10" name="vorgangsid" not-null="true" type="long"/>
<property column="BAUSPARNR" length="11" name="bausparnr" type="string"/>
<property column="CODIERUNGSART" length="1" name="codierungsart" type="byte"/>
<property column="ANWENDUNGSNAME" length="8" name="anwendungsname" type="string"/>
<property column="FEHLER" length="250" name="fehler" type="string"/>
<property column="SBM" length="8" name="sbm" type="string"/>
<property column="HERKUNFTKZ" length="1" name="herkunftkz" type="string"/>
<property column="BRIEFDATUM" length="7" name="briefdatum" type="timestamp"/>
<property column="AES" length="2" name="aes" type="string"/>
</class>
</hibernate-mapping>
Persistent ClassCode:
package de.kreditwerk.diamant.connectors.diamantdb.model;
import java.io.Serializable;
import java.util.Date;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
public class Codierung extends TransferObject implements Serializable
{
static final long serialVersionUID = -1257110293852996404L;
/** identifier field */
private Long oid;
/** persistent field */
private long vorgangsid;
/** nullable persistent field */
private String bausparnr;
/** nullable persistent field */
private byte codierungsart;
/** nullable persistent field */
private String anwendungsname;
/** nullable persistent field */
private String fehler;
/** nullable persistent field */
private String sbm;
/** nullable persistent field */
private String herkunftkz;
/** nullable persistent field */
private Date briefdatum;
/** nullable persistent field */
private String aes;
/** full constructor */
public Codierung(
long vorgangsid,
String bausparnr,
byte codierungsart,
String anwendungsname,
String fehler,
String sbm,
String herkunftkz,
Date briefdatum,
String aes)
{
this.vorgangsid = vorgangsid;
this.bausparnr = bausparnr;
this.codierungsart = codierungsart;
this.anwendungsname = anwendungsname;
this.fehler = fehler;
this.sbm = sbm;
this.herkunftkz = herkunftkz;
this.briefdatum = briefdatum;
this.aes = aes;
}
/** default constructor */
public Codierung()
{
}
/** minimal constructor */
public Codierung(long vorgangsid)
{
this.vorgangsid = vorgangsid;
}
public Long getOid()
{
return this.oid;
}
protected void setOid(Long oid)
{
this.oid = oid;
}
public long getVorgangsid()
{
return this.vorgangsid;
}
public void setVorgangsid(long vorgangsid)
{
this.vorgangsid = vorgangsid;
}
public String getBausparnr()
{
return this.bausparnr;
}
public void setBausparnr(String bausparnr)
{
this.bausparnr = bausparnr;
}
public byte getCodierungsart()
{
return this.codierungsart;
}
public void setCodierungsart(byte codierungsart)
{
this.codierungsart = codierungsart;
}
public String getAnwendungsname()
{
return this.anwendungsname;
}
public void setAnwendungsname(String anwendungsname)
{
this.anwendungsname = anwendungsname;
}
public String getFehler()
{
return this.fehler;
}
public void setFehler(String fehler)
{
this.fehler = fehler;
}
public String getSbm()
{
return this.sbm;
}
public void setSbm(String sbm)
{
this.sbm = sbm;
}
public String getHerkunftkz()
{
return this.herkunftkz;
}
public void setHerkunftkz(String herkunftkz)
{
this.herkunftkz = herkunftkz;
}
public Date getBriefdatum()
{
return this.briefdatum;
}
public void setBriefdatum(Date briefdatum)
{
this.briefdatum = briefdatum;
}
public String getAes()
{
return this.aes;
}
public void setAes(String aes)
{
this.aes = aes;
}
public String toString()
{
return new ToStringBuilder(this).append("oid", getOid()).toString();
}
public boolean equals(Object other)
{
if (!(other instanceof Codierung))
{
return false;
}
Codierung castOther = (Codierung) other;
return new EqualsBuilder().append(this.getOid(), castOther.getOid()).isEquals();
}
public int hashCode()
{
return new HashCodeBuilder().append(getOid()).toHashCode();
}
}
Code between sessionFactory.openSession() and session.close():Code:
public void update(TransferObject transferObject) throws DiAmantDBSQLException
{
Session openSession = this.getSessionFactory().openSession(); // 1
try
{
openSession.setAutoCommit(false); // 2
openSession.update(transferObject); // 3
openSession.flush(); // 4
}
catch (Exception ex)
{
throw new DiAmantDBSQLException(
"Fehler beim Aktualisieren des Datensatzes.",
ex,
this.getClass(),
DiAmantDBSQLException.SEVERITY_CRITICAL,
2010032);
}
finally
{
this.closeSession(openSession); // 5
}
}
Full stack trace of any exception that occurs:Code:
Caused by: net.sf.hibernate.HibernateException: SQL insert, update or delete failed (row not found)
at net.sf.hibernate.impl.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java(Compiled Code))
at net.sf.hibernate.persister.EntityPersister.update(EntityPersister.java(Compiled Code))
at net.sf.hibernate.persister.EntityPersister.update(EntityPersister.java(Compiled Code))
at net.sf.hibernate.impl.ScheduledUpdate.execute(ScheduledUpdate.java(Compiled Code))
at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java(Compiled Code))
at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java(Inlined Compiled Code))
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java(Compiled Code))
System environment we are using:
Oracle 9i
BEA Weblogic 8.1 SP 1 (Cluster)