简体   繁体   中英

Wrong auto increment in embedded Derby/ Java DB

I'm developing an accounting program that uses an Apache Derby database in embedded mode. I have a table Branch with two columns:

CREATE TABLE Branch(
     idBranch INT NOT NULL PRIMARY KEY 
     GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), 
     place VARCHAR(255) NOT NULL
);

When I insert a new record in the Branch table, the auto increment by 1 doesn't work properly. I'm getting the following result:

+----------+
| idBranch |
+----------+
| 1        |
| 101      |
| 201      |
| 301      |
+----------+

But the result should be the following:

+----------+
| idBranch |
+----------+
| 1        |
| 2        |
| 3        |
| 4        |
+----------+

Here is how I connect to the database:

private static final String DRIVER = "org.apache.derby.jdbc.EmbeddedDriver";

public static Connection createConnection() {
    Connection connection = null;
    try {
        Class.forName(DRIVER);
        connection = DriverManager.getConnection("jdbc:derby:" + DATABASE);
    } catch (ClassNotFoundException ex) {
        logger.log(Level.SEVERE, "JDBC Driver not loaded!", ex);
        System.exit(1);
    } catch (SQLException ex) {
        // create the database
        DerbyDB derbyDB = new DerbyDB();
        connection = derbyDB.create();
    }
    return connection;
}

And here is the method to insert the new record in the Branch table:

private static final String CREATE_QUERY = "INSERT INTO Branch(place) VALUES(?)";

public int createBranch(Branch branch) {
    Connection connection = DerbyDAOFactory.createConnection();
    try {
        PreparedStatement statement = connection.prepareStatement(CREATE_QUERY, Statement.RETURN_GENERATED_KEYS);
        statement.setString(1, branch.getPlace());
        statement.execute();
        ResultSet result = statement.getGeneratedKeys();
        if(result.next()) {
            return result.getInt(1);
        }
    } catch (SQLException ex) {
        logger.log(Level.SEVERE, null, ex);
    }
    return -1;
}

Why do I get this result?

The sequence you are observing is a consequence of this bug: https://issues.apache.org/jira/browse/DERBY-5151

The following documentation describes why it is happening: https://db.apache.org/derby/docs/10.9/ref/rrefproperpreallocator.html

To summarize... The generated values are pre-allocated (100 values at a time by default). When the database is shutdown incorrectly those pre-allocated values are leaked - they are simply discarded and when the database is booted again the allocator starts counting where it left off (introducing a gap in the sequence).

In other words this is expected behavior - to avoid it make sure you are closing your database in an orderly manner:

DriverManager.getConnection("jdbc:derby:;shutdown=true")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM