Subject Batch Update and Blobs
Author Michael Kaegi
Hi Jaybird Developers


I'm using Hibernate 3.2 + Jaybird 2.1.1 + Firebird 1.5


In hibernate I try to save a bean that contains a collection of other
beans that contains a collection of blobs...

E.g..

Foo
Bar
Blob
Blob
Bar
Blob
Blob

session.save(foo);

... but following exception is thrown:

org.hibernate.exception.GenericJDBCException: could not insert:
[ch.bw.worknavigator.hibernatetest.FooBlob]
at
org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
at
org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
at
org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at
org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2263)
at
org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2656)
at
org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:52)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at
org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
at
org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:139)
at
org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at
org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at
ch.bw.worknavigator.hibernatetest.Test.testFooBlobs(Test.java:56)
at ch.bw.worknavigator.hibernatetest.Test.main(Test.java:32)
Caused by: org.firebirdsql.jdbc.FBDriverNotCapableException: Not yet
implemented.
at
org.firebirdsql.jdbc.field.FBBlobField.getCachedObject(FBBlobField.java:178)
at
org.firebirdsql.jdbc.AbstractPreparedStatement.addBatch(AbstractPreparedStatement.java:767)
at
org.hibernate.jdbc.BatchingBatcher.addToBatch(BatchingBatcher.java:31)
at
org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2243)
... 10 more




I have written a small example(testcase) in jdbc to reproduce the problem
without hibernate:

The example inserts two records in a batch update...



import java.io.ByteArrayInputStream;

import java.sql.*;

public class Test {

public static void main(String[] args) throws Exception {

// get driver...

String databaseURL =
"jdbc:firebirdsql:127.0.0.1:d:/test.fdb?sql_dialect=3";
String user = "sysdba";
String password = "masterkey";
String driverName = "org.firebirdsql.jdbc.FBDriver";

Driver d = null;
Connection c = null;
Statement s = null;
PreparedStatement ps = null;

try {
Class.forName(driverName);
} catch (java.lang.ClassNotFoundException e) {
System.out.println("Firebird JCA-JDBC driver not found in
class path");
System.out.println(e.getMessage());
return;
}

try {
d = DriverManager.getDriver(databaseURL);
System.out.println("Firebird JCA-JDBC driver version " +
d.getMajorVersion() + "." + d.getMinorVersion() + " registered with driver
manager.");
} catch (SQLException e) {
System.out.println("Unable to find Firebird JCA-JDBC driver
among the registered drivers.");
showSQLException(e);
return;
}

// get connection...

try {
c = DriverManager.getConnection(databaseURL, user, password);
System.out.println("Connection established.");
} catch (SQLException e) {
e.printStackTrace();
System.out.println("Unable to establish a connection through
the driver manager.");
showSQLException(e);
return;
}

// get driver info...
try {
java.sql.DatabaseMetaData dbMetaData = c.getMetaData ();

// Ok, let's query a driver/database capability
if (dbMetaData.supportsBatchUpdates())
System.out.println ("Batch updates are supported.");
else
System.out.println ("Batch updates are not supported.");


}
catch (java.sql.SQLException e) {
System.out.println ("Unable to extract database meta data.");
showSQLException (e);
}

// create table...

c.setAutoCommit(true);

s = c.createStatement();

try {
System.out.println("DROP TABLE BLOBTEST");
s.executeUpdate("DROP TABLE BLOBTEST");
} catch (java.sql.SQLException e) {
}

System.out.println("CREATE TABLE BLOBTEST(ID NUMERIC(18,0) NOT
NULL PRIMARY KEY, NAME VARCHAR(10), DATA BLOB SUB_TYPE 0 SEGMENT SIZE
80)");
s.executeUpdate("CREATE TABLE BLOBTEST(ID NUMERIC(18,0) NOT NULL
PRIMARY KEY, NAME VARCHAR(10), DATA BLOB SUB_TYPE 0 SEGMENT SIZE 80)");

c.setAutoCommit(false);



// -->>
// -->>



// insert two records in a batch update...

try {

// record 1...

byte[] bytes1 = new byte[]{65, 65, 65, 65};

ByteArrayInputStream bais = new ByteArrayInputStream(bytes1);

System.out.println("INSERT INTO BLOBTEST ( ID, NAME, DATA )
VALUES ( ?, ?, ?)");
ps = c.prepareStatement("INSERT INTO BLOBTEST ( ID, NAME, DATA
) VALUES ( ?, ?, ?)");
ps.setLong(1, 1);
ps.setString(2, "One");
ps.setBinaryStream(3, bais, bytes1.length);

ps.addBatch(); // => throws
org.firebirdsql.jdbc.FBDriverNotCapableException: Not yet implemented.
<------------------

// record 2...

// byte[] bytes2 = new byte[]{66, 66, 66, 66};
//
// bais = new ByteArrayInputStream(bytes2);
//
// System.out.println("INSERT INTO BLOBTEST ( ID, NAME, DATA )
VALUES ( ?, ?, ?)");
// ps.setLong(1, 2);
// ps.setString(2, "Two");
// ps.setBinaryStream(3, bais, bytes2.length);
// ps.addBatch();

ps.executeBatch();

c.commit();



// <<--
// <<--


} catch (Exception ex) {
ex.printStackTrace();
try {
if (c != null)
c.rollback();
} catch (SQLException e) {
showSQLException(e);
}
} finally {
System.out.println("Closing database resources.");
try {
if (s != null)
s.close();
} catch (SQLException e) {
showSQLException(e);
}
try {
if (ps != null)
ps.close();
} catch (SQLException e) {
showSQLException(e);
}
try {
if (c != null)
c.close();
} catch (SQLException e) {
showSQLException(e);
}
}

}

// Display an SQLException which has occured in this application.
private static void showSQLException(SQLException e) {
java.sql.SQLException next = e;
while (next != null) {
System.out.println(next.getMessage());
System.out.println("Error Code: " + next.getErrorCode());
System.out.println("SQL State: " + next.getSQLState());
next = next.getNextException();
}
}
}



If I execute it...

org.firebirdsql.jdbc.FBDriverNotCapableException: Not yet implemented.
at
org.firebirdsql.jdbc.field.FBBlobField.getCachedObject(FBBlobField.java:178)
at
org.firebirdsql.jdbc.AbstractPreparedStatement.addBatch(AbstractPreparedStatement.java:767)
at Test.main(Test.java:101)



Note: If I just insert the id and name (no Blob) it works...



I read in the Jaybird FAQ that the driver dosn't support Batch Updates.


Can somebody tell me if you plan to implement or allready working on...

java.sql.PreparedStatement:

addBatch(String sql)
clearBatch()
executeBatch()

...and if so when (in which release) it will be available?



Thanx
Michi











[Non-text portions of this message have been removed]