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]

# 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
# 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