CachedRowSetImpl in JDK 1.6

Hello,

My little program throws exceptions using JDK 1.6. With JDK 1.5.x everything works as expected. I have tried with Firebird 1.5 (using Jaybird driver) and Derby 10.2.2.0 databases. In both cases the error seems to be related to table (Derby) or column names (Firebird), and it occurs when trying to acceptChanges. Is CachedRowSetImpl "broken" in JDK 1.6, am I doing something wrong, or what is going on?

Steps to reproduce (with Derby):

Create a database EMPLOYEE and table TEST with 2 columns, name (varchar) and salary (integer). I am a novice with Derby and just used the graphical tools of Netbeans to create the table.

With the database server running, try to execute the following code:

import java.sql.*;

import javax.sql.RowSet.*;

import com.sun.rowset.*;

publicclass Main{

public Main(){

}

publicstaticvoid main(String[] args){

try{

Class.forName("org.apache.derby.jdbc.ClientDriver");

String url ="jdbc:derby://localhost:1527/EMPLOYEE";

Connection dbConn = DriverManager.getConnection(url);

String query ="SELECT * FROM TEST";

Statement stat = dbConn.createStatement();

ResultSet rs = stat.executeQuery(query);

CachedRowSetImpl crs =new CachedRowSetImpl();

crs.setType(ResultSet.TYPE_SCROLL_SENSITIVE);

crs.setConcurrency(ResultSet.CONCUR_UPDATABLE);

crs.populate(rs);

crs.moveToInsertRow();

// Add a record.

crs.updateString("NAME","Bill");

crs.updateInt("SALARY", 55000);

crs.insertRow();

crs.moveToCurrentRow();

crs.acceptChanges(dbConn);

crs.beforeFirst();

while (crs.next()){

System.out.println(

crs.getString("NAME") +"\t\t" +

crs.getFloat("SALARY"));

}

crs.close();

rs.close();

stat.close();

}

catch (Exception e){

e.printStackTrace();

}

}

}

Thanks,

- Jori

[2973 byte] By [_jms_a] at [2007-11-26 15:20:52]
# 1
Would you like to tell us more about the error messages. Like what they actually are for example. And the stack-trace.
cotton.ma at 2007-7-8 11:49:10 > top of Java-index,Database Connectivity,Java Database Connectivity (JDBC)...
# 2

Here are the stack traces. The first one is for Derby 10.2.2.0:

java.sql.SQLException: Table name can not be null

at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown Source)

at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)

at org.apache.derby.client.am.DatabaseMetaData.getPrimaryKeys(Unknown Source)

at com.sun.rowset.internal.CachedRowSetWriter.insertNewRow(CachedRowSetWriter.java:755)

at com.sun.rowset.internal.CachedRowSetWriter.writeData(CachedRowSetWriter.java:313)

at com.sun.rowset.CachedRowSetImpl.acceptChanges(CachedRowSetImpl.java:862)

at com.sun.rowset.CachedRowSetImpl.acceptChanges(CachedRowSetImpl.java:921)

at Main.main(Main.java:28)

Caused by: org.apache.derby.client.am.SqlException: Table name can not be null

at org.apache.derby.client.am.DatabaseMetaData.getPrimaryKeysX(Unknown Source)

... 6 more

javax.sql.rowset.spi.SyncProviderException: Table name can not be null

at com.sun.rowset.CachedRowSetImpl.acceptChanges(CachedRowSetImpl.java:889)

at com.sun.rowset.CachedRowSetImpl.acceptChanges(CachedRowSetImpl.java:921)

at Main.main(Main.java:28)

The second is for Firebird 1.5 using Jaybird 2.1.1:

java.lang.ArrayIndexOutOfBoundsException: 2

at com.sun.rowset.internal.CachedRowSetWriter.insertNewRow(CachedRowSetWriter.java:760)

at com.sun.rowset.internal.CachedRowSetWriter.writeData(CachedRowSetWriter.java:313)

at com.sun.rowset.CachedRowSetImpl.acceptChanges(CachedRowSetImpl.java:862)

at com.sun.rowset.CachedRowSetImpl.acceptChanges(CachedRowSetImpl.java:921)

at Main.main(Main.java:32)

I had commented and edited some rows, that's why the row numbers are different in Main.java. In short, I created the TEST table to Firebird's EMPLOYEE example database and changed:

Class.forName("org.firebirdsql.jdbc.FBDriver");

String url = "jdbc:firebirdsql:localhost:P:/Firebird/Firebird_1_5/Examples/EMPLOYEE.FDB";

Connection dbConn = DriverManager.getConnection(url, "SYSDBA", "masterkey");

Also, originally, before simplifying the code the exception and stack trace were different: there was SQLException about "invalid column name". I did not save that data.

Thanks,

- Jori

_jms_a at 2007-7-8 11:49:10 > top of Java-index,Database Connectivity,Java Database Connectivity (JDBC)...
# 3
Has anybody been able to use CachedRowSetImpl under JDK 1.6? Which database & Java version? My build is 1.6.0-b105.- Jori
_jms_a at 2007-7-8 11:49:10 > top of Java-index,Database Connectivity,Java Database Connectivity (JDBC)...
# 4
Yes i am using with mysql server 5.0 and java 1.6-b105. The only problem encounter is when the resultset contain a blob field an move it to the cachedrowset, when i try to read the field it give me an Data Type Mismatch.
BlackHolea at 2007-7-8 11:49:10 > top of Java-index,Database Connectivity,Java Database Connectivity (JDBC)...
# 5

I have learned that I must do two changes to get the program run under JDK 1.6:

dbConn.setAutoCommit(false); // Necessary only for Firebird

crs.setTableName("TEST");

(Thanks for kalpanavaka for pointing this out in another thread.) Note that under JDK 1.5.x the program works fine without setTableName call. I studied the source code (thanks Sun for this possibility) and it seems that from now on the table name is indeed necessary if you update the database.

I ran into another problem, though, when inserting a row to a table which has a primary key. Before JDK 1.6 I was able to set that field to null, and the correct value was generated in my Firebird database automatically (using a generator). In 1.6 duplicate PK values are checked before trying to insert. The check fails for me: PK with null leads to NullPointerException. I guess the only way out is to read the current generator value first, calculate the next one and use it in PK field.

Cheers,

- Jori

_jms_a at 2007-7-8 11:49:10 > top of Java-index,Database Connectivity,Java Database Connectivity (JDBC)...