javahsqldbauto-incrementibatisddlutils

Auto-incrementation with HSQLDB (2.2.8) + DDLUtils


I want to use HSQLDB as an embedded database but am having trouble getting it to auto-increment.

As far as I understand, [CALL] IDENTITY() can be used to get the last primary key value. However, experiments through both iBatis and HSQLDB's DatabaseManagerSwing continually return a 0 value.

How can I get auto-incrementation to work with HSQLDB?

Edit:

I didn't mention that I'm using DDLUtils to autogenerate tables. The following does not suit HSQLDB:

<?xml version="1.0"?>
<!DOCTYPE database SYSTEM "http://db.apache.org/torque/dtd/database.dtd">

<database name="testdb">

    <table name="users">
        <!-- using autoincrement attribute below causes
        "primary key already exists" exception -->
        <column name="id" type="INTEGER" primaryKey="true" />
        <column name="username" type="VARCHAR" size="30" />
        <column name="password" type="VARCHAR" size="100" />
    </table>

</database>

Also, here is the iBatis SQL map used for the domain class:

<insert id="insertUser" parameterClass="user">
    <selectKey keyProperty="id" resultClass="int">
        CALL IDENTITY()
    </selectKey>
INSERT INTO USERS
( USERNAME, PASSWORD ) 
VALUES
( #username#, #password#)       
</insert>

Solution

  • Here's an example that prints out

    0
    1
    2
    

    on my machine:

    import java.io.File;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.Statement;
    import java.sql.ResultSet;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Date;
    
    public class Test {
    
      public static void main(String[] args) throws Exception {
    
        File dbDir = new File("/tmp/identity_test"); 
        String connectionTemplate = "jdbc:hsqldb:file:%s/test";
        String connStr = String.format(connectionTemplate, dbDir);
        Connection connection = DriverManager.getConnection(connStr, "", "");
        Statement s = connection.createStatement();
        s.execute("CREATE TABLE test (id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, s VARCHAR(10))");
        PreparedStatement psInsert = connection.prepareStatement("INSERT INTO test (s) VALUES (?)");
        for (int i = 0; i < 3; i++) {
          psInsert.setString(1, "hello");
          psInsert.executeUpdate();
          PreparedStatement psIdentity = connection.prepareStatement("CALL IDENTITY()");
          ResultSet result = psIdentity.executeQuery();
          result.next();
          int identity = result.getInt(1);
          result.close();
          System.out.println(identity);
        }
        connection.close();
      }
    }