使用Apache Derby的Spring Boot将主键增加100

时间:2018-07-16 14:23:21

标签: spring-boot derby

我有带有Derby Database的spring boot App。在应用程序属性文件中,下面是配置。

spring.datasource.url=jdbc:derby://localhost:1600/derbydataLogger
spring.datasource.username=
spring.datasource.password=
spring.datasource.driver-class-name=org.apache.derby.jdbc.ClientDriver
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
spring.datasource.initialize=false


CREATE TABLE "DCS"."DEVICES" (
  "ID" bigint generated by default as identity,
  "DEVICE_NAME" varchar(45) NOT NULL,
  "IP_ADDRESS" varchar(60) NOT NULL,
  "PORT" int NOT NULL,
  "IS_CONNECTED" boolean DEFAULT false,
  "UPDATED_DATE" TIMESTAMP DEFAULT NULL,
   CONSTRAINT PK_devices_ID PRIMARY KEY ("ID")
);

我注意到,当有一个带有自动生成的主表的表时 键,则INSERT自动递增失败。而不是增加值 加1,有时Derby将主键增加100或1000或其他 随机值。

我无法复制它,因为它是随机的。

例如,我有一个名为“ DEVICE”的表,并且我插入了4行,并且 我得到以下自动生成的键:

1. INSERT: auto generated primary key: 806 
2. INSERT: auto generated primary key: 807 
3. INSERT: auto generated primary key: *904* 
4. INSERT: auto generated primary key: *1004* 
5. INSERT: auto generated primary key: 1005 

应将其递增1。预期序列应为:

1. INSERT: auto generated primary key: 806 
2. INSERT: auto generated primary key: 807 
3. INSERT: auto generated primary key: 808 
4. INSERT: auto generated primary key: 809 
5. INSERT: auto generated primary key: 810 

有人遇到这个奇怪的错误吗?您有什么建议,如何 开始调试了吗?我无法复制它。

2 个答案:

答案 0 :(得分:2)

这是由于pre-allocation of values for auto-increment columns造成的。 Derby是内存数据库,在数据库首次加载到内存中时会缓存自动增量值。然后,使用缓存而不是一次又一次地查询数据库来生成自动递增列的将来值。如果数据库未正确关闭,则缓存中未使用的值将永远丢失。

您可以通过以下两种方式解决此问题:

  1. ;shutdown=true添加到JDBC URL。当应用程序结束时,这将关闭数据库。
  2. derby.language.sequence.preallocator属性设置为1(默认值为100)。这将确保从不缓存列值。

请注意,大多数数据库的序列行为相似。例如,H2具有完全相同的行为,但使用的缓存大小为32而不是像Derby那样的100

从这里引出Derby Auto Increment by 100 when specified as 1

答案 1 :(得分:0)

下面的代码对我有用。

@Value("${spring.datasource.url}")
private String connectionURL;

@PreDestroy
public void shutdown() {
    System.out.println("Shutting down.. DB and Network Server Control..");
    try {
        DriverManager.getConnection(connectionURL+";shutdown=true");
        if(nc !=null)
            nc.shutdown();
    } catch (Exception e) {
        e.printStackTrace();
    }

}

此处“ nc”是对应用程序中NetworkServerControl实例的引用。

使用@PreDestory该方法将按顺序关闭derby数据库,并且在重新启动后也可以正确生成主键。

在正确关闭应用程序后,您将获得以下类似异常信息。

Caused by: ERROR 08006: DERBY SQL error: ERRORCODE: 45000, SQLSTATE: 08006, SQLERRMC: Database 'derbycheckdb' shutdown.
at org.apache.derby.client.am.ClientConnection.completeSqlca(Unknown Source)

此异常表明数据库关闭正常,并且那里没有其他异常。请参阅此文档以获取更多详细信息。 Shutting down Derby or an individual database

注意:

此代码假定正常启动了Spring Boot应用程序(例如从终端运行该应用程序并执行ctrl+c以停止该应用程序或其他方式,如果有的话)