Hallo zusammen,
beim Verwenden der StatelessSession zum Insert von Massendaten bekomme ich nach dem ersten Insert folgenden Fehler:
Code:
Caused by: java.sql.SQLException: Already closed
at org.jboss.resource.adapter.jdbc.WrappedStatement.close(WrappedStatement.java:69)
at org.hibernate.jdbc.AbstractBatcher.closePreparedStatement(AbstractBatcher.java:526)
at org.hibernate.jdbc.AbstractBatcher.closeStatement(AbstractBatcher.java:265)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:245)
... 54 more
Ich habe es auch mal auf dem IBM Websphere anstatt dem JBossAS versucht - da bekomme ich leider den gleichen Fehler "java.sql.SQLException: Already closed".
Meine Util-Methode ist:
Code:
/**
* @param dots
* a list collecting <code>DOT</code>
* @return a list collecting <code>DOT</code> from <code>dots</code> inserted or updated
*/
public List statelessInsertUpdateOrDeleteDots(
final StatelessSession session, final List dots)
throws NullPointerException {
if (session == null) {
throw new NullPointerException("Error - session is null.");
} else if (dots == null) {
throw new NullPointerException("Error - dots is null.");
}
List savedUpdatedDots = Collections.EMPTY_LIST;
if (!dots.isEmpty()) {
ListHelper listHelper = new ListHelper();
Timestamp timestamp = null;
int dotsSize = dots.size();
for (int i = 0; i < dotsSize; i++) {
DOT dot = (DOT)dots.get(i);
if (dot.isDeleted()) {
session.delete(dot);
dot = null;
} else if (dot.isCreated() || dot.isChanged()) {
if (dot instanceof CreateTimeInfoProvider
|| dot instanceof ChangeTimeInfoProvider) {
if (timestamp == null) {
timestamp = (Timestamp)session
.createSQLQuery(
"SELECT current_timestamp FROM sysibm.sysdummy1")
.uniqueResult();
}
if (dot instanceof CreateTimeInfoProvider) {
((CreateTimeInfoProvider)dot).setCreated(timestamp);
}
if (dot instanceof ChangeTimeInfoProvider) {
((ChangeTimeInfoProvider)dot)
.setLastModified(timestamp);
}
}
if (dot.isCreated()) {
session.insert(dot);
} else if (dot.isChanged()) {
session.update(dot);
}
} else {
continue;
}
savedUpdatedDots = listHelper.saveAddElementIgnoreNull(
savedUpdatedDots, dot);
}
}
return savedUpdatedDots;
}
Die StatelessSession wird hier erzeugt (ich verwende CMT und schliesse die Session deshalb nur im Fehlerfall):
Code:
protected Object dbExectueStateless(
final StatelessHibernateCommand statelessHibernateCommand) {
final SessionFactory sessionFactory = SessionFactoryManager
.getSessionFactory();
final StatelessSession statelessSession = sessionFactory
.openStatelessSession();
try {
final Object result = statelessHibernateCommand
.run(statelessSession);
return result;
} catch (final Throwable e) {
statelessSession.close();
LOGGER.error(e, e);
if (e instanceof HibernateRuntimeException) {
throw new ServerRuntimeException("Error - database error.", e);
} else {
throw new ServerRuntimeException("Error - server error.", e);
}
}
}
Meine hibernate.cfg.xml ist:
Code:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">
com.ibm.db2.jcc.DB2Driver
</property>
<property name="hibernate.connection.datasource">
java:jdbc/cypris/cyprisdb
</property>
<property name="hibernate.dialect">
de.bredex.server.core.hibernate.dialect.DB2DialectBX
</property>
<property name="hibernate.session_factory_name">
java:hibernate/Cypris/SessionFactory
</property>
<property name="hibernate.transaction.manager_lookup_class">
org.hibernate.transaction.JBossTransactionManagerLookup
</property>
<property name="hibernate.default_schema">
CYPRIS
</property>
<property name="hibernate.show_sql">
false
</property>
<property name="hibernate.format_sql">
true
</property>
<property name="hibernate.use_sql_comments">
false
</property>
<property name="hibernate.jdbc.batch_size">
50
</property>
<property name="hibernate.cache.use_second_level_cache">
false
</property>
<property name="hibernate.cache.provider_class">
org.hibernate.cache.NoCacheProvider
</property>
<property name="hibernate.current_session_context_class">
jta
</property>
<property name="hibernate.connection.aggressive_release">
false
</property>
<property name="hibernate.transaction.factory_class">
org.hibernate.transaction.CMTTransactionFactory
</property>
</session-factory>
</hibernate-configuration>
Wenn ich Massendaten mit der StatelessSession lösche, dann bekomme ich keinen Fehler. Mit Debugging konnte ich ungefähr erkennen, dass es zu dem Fehler kommt, wenn Hibernate das zweite Insert-Statement "preparen" will - und ich
glaube Hibernate will das erste Insert-Statement wiederverwenden, obwohl es schon geschlossen wurde.