views:

57

answers:

3

I have JDBC code which inserts into a database table by executing a PreparedStatement. When I run the code on an in-memory HSQLDB database (as part of a JUnit test) I get a SQLFeatureNotSupportedException with the only information being the message "feature not supported" and the vendor code -1500. What I'm doing is a basic insertion into a table -- I can't imagine that this is unsupported in the latest HSQLDB.

My code:

public Observations saveOrUpdate(final Observations observations)
{
    try
    {
        if (connection == null)
        {
            connection = getJdbcTemplate().getDataSource().getConnection();
        }

        // create the prepared statement
        String sql = "INSERT INTO " + Observations.TABLE_NAME +
                     " (OBS_YEAR, WINTER, SPRING, SUMMER, FALL, ANNUAL, DATA_TYPE, CREATED_DATE, UPDATED_DATE, " +
                     Observations.ID_COLUMN_NAME +
                     ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setInt(1, observations.getYear());
        preparedStatement.setBigDecimal(2, observations.getJan());
        preparedStatement.setBigDecimal(3, observations.getFeb());
        preparedStatement.setBigDecimal(4, observations.getMar());
        preparedStatement.setBigDecimal(5, observations.getApr());
        preparedStatement.setBigDecimal(6, observations.getMay());
        preparedStatement.setString(7, observations.getDataType().toString());
        preparedStatement.setTimestamp(8, new Timestamp(observations.getCreatedDate().getTime()));
        preparedStatement.setTimestamp(9, new Timestamp(observations.getUpdatedDate().getTime()));
        preparedStatement.setLong(10, observations.getId());
        preparedStatement.executeUpdate(sql);

        return observations;
    }
    catch (SQLException ex)
    {
        throw new RuntimeException(ex);
    }
}

Can anyone suggest what may be the problem or anything else I should investigate further? Thanks in advance for your help.

--James

A: 

Systemic issues with HSQLDB are often due to mismatches in server vs. driver version (any mismatch at all will not work in my experience).

I mostly suspect this isn't your issue. Since you said the db is "in memory," I'm guessing the server & driver are the same .jar file. But in case my guess is wrong, I thought I'd throw this out there.

Drew Wills
Because this is speculation, shouldn't this be a comment to the question and not an answer?
Jacob Tomaw
@Jacob Tomaw -- should it? I have never seen a guideline like that. And what's more, aren't 98% of answers to questions on this site speculation on some level? If the asking person knew enough detail about his issue such that there were no need for speculation in finding the cause, wouldn't he probably have been able to find the answer himself?
Drew Wills
@Drew Willis Your speculation is that your answer is unhelpful. To me, it would be more helpful to ask the question that will clarify the issue for you and that the asker will know the answer to "When you say this is an 'in memory' data base, you mean that database and the test are running in the same JVM?" as a comment. Once that question is answered, you could provide an informed answer.
Jacob Tomaw
+3  A: 

You need to call preparedStatement.executeUpdate() (without the parameter sql).

You called the method PreparedStatement.executeUpdate(String sql), which is illegal according to the JDBC specification. It doesn't really make sense to pass the SQL statement again, because you have already passed it when you created the PreparedStatement object. Even thought you pass the same string, it's not legal to call this method. It's a bit strange that calling a method is not legal :-) but that's the way it is. All standard conforming JDBC drivers need to throw an exception in this case.

But I agree the error message is cryptic.

Thomas Mueller
Bingo, you are the winner. Thanks so much!
James Adams
+1  A: 

Some further info I found in http://hsqldb.org/doc/changelog_1_7_2.txt:

The execute(String sql), executeUpdate(String sql) and executeQuery(String sql) 
commands are no-longer supported for PreparedStatements according to JDBC specs. 
Use an ordinary Statement for calling these methods.
James Adams