Scala Slick,H2插入查询自动增量ID

Scala Slick,H2插入查询自动增量ID,scala,h2,slick,anorm,slick-2.0,Scala,H2,Slick,Anorm,Slick 2.0,我有一张H2表格: CREATE TABLE computer (id BIGINT NOT NULL, name VARCHAR(255) NOT NULL, introduced TIMESTAMP, discontinued TIMESTAMP, company_id BIGINT, CONSTRAINT pk_computer PRIMARY KEY (id)); CREATE SEQUENCE computer_seq START WITH 1000; Slick为其自动生成的类:

我有一张H2表格:

CREATE TABLE computer (id BIGINT NOT NULL, name VARCHAR(255) NOT NULL, introduced TIMESTAMP, discontinued TIMESTAMP, company_id BIGINT, CONSTRAINT pk_computer PRIMARY KEY (id));
CREATE SEQUENCE computer_seq START WITH 1000;
Slick为其自动生成的类:

  case class ComputerRow(id: Long, name: String, introduced: Option[java.sql.Timestamp], discontinued: Option[java.sql.Timestamp], companyId: Option[Long])
  /** GetResult implicit for fetching ComputerRow objects using plain SQL queries */
  implicit def GetResultComputerRow(implicit e0: GR[Long], e1: GR[String], e2: GR[Option[java.sql.Timestamp]], e3: GR[Option[Long]]): GR[ComputerRow] = GR{
    prs => import prs._
    ComputerRow.tupled((<<[Long], <<[String], <<?[java.sql.Timestamp], <<?[java.sql.Timestamp], <<?[Long]))
  }
  /** Table description of table COMPUTER. Objects of this class serve as prototypes for rows in queries. */
  class Computer(tag: Tag) extends Table[ComputerRow](tag, "COMPUTER") {
    def * = (id, name, introduced, discontinued, companyId) <> (ComputerRow.tupled, ComputerRow.unapply)
    /** Maps whole row to an option. Useful for outer joins. */
    def ? = (id.?, name.?, introduced, discontinued, companyId).shaped.<>({r=>import r._; _1.map(_=> ComputerRow.tupled((_1.get, _2.get, _3, _4, _5)))}, (_:Any) =>  throw new Exception("Inserting into ? projection not supported."))

    /** Database column ID PrimaryKey */
    val id: Column[Long] = column[Long]("ID", O.PrimaryKey)
    /** Database column NAME  */
    val name: Column[String] = column[String]("NAME")
    /** Database column INTRODUCED  */
    val introduced: Column[Option[java.sql.Timestamp]] = column[Option[java.sql.Timestamp]]("INTRODUCED")
    /** Database column DISCONTINUED  */
    val discontinued: Column[Option[java.sql.Timestamp]] = column[Option[java.sql.Timestamp]]("DISCONTINUED")
    /** Database column COMPANY_ID  */
    val companyId: Column[Option[Long]] = column[Option[Long]]("COMPANY_ID")

    /** Foreign key referencing Company (database name FK_COMPUTER_COMPANY_1) */
    lazy val companyFk = foreignKey("FK_COMPUTER_COMPANY_1", companyId, Company)(r => r.id, onUpdate=ForeignKeyAction.Restrict, onDelete=ForeignKeyAction.Restrict)
  }
  /** Collection-like TableQuery object for table Computer */
  lazy val Computer = new TableQuery(tag => new Computer(tag))
抛出错误

[JdbcSQLException: NULL not allowed for column "ID"; SQL statement: INSERT INTO "COMPUTER" ("NAME","INTRODUCED","DISCONTINUED","COMPANY_ID") VALUES (?,?,?,?) [23502-175]]
同样的方法也适用于MySQL和PostgreSQL,所以我猜H2没有相同的主ID自动递增功能?那么,如何使用slick使插入件工作

这是使用Anorm的同一表格的工作示例:

DB.withConnection { implicit connection =>
    SQL(
        """
            insert into computer values (
                (select next value for computer_seq), 
                {name}, {introduced}, {discontinued}, {company_id}
            )
        """
    ).on(
        'name -> "name",
        'introduced -> new Timestamp((new Date).getTime),
        'discontinued -> new Timestamp((new Date).getTime),
        'company_id -> 123
    ).executeUpdate()
}

尝试为case类提供id的默认值,如下所示:

case class ComputerRow(id: Long = 0, name: String, introduced: Option[java.sql.Timestamp], discontinued: Option[java.sql.Timestamp], companyId: Option[Long])
我不确定
H2
是否正确,但当我使用
Postgres
时,我通常会为
id
字段指定默认值,以符合表单Slick的最终检查,然后在数据库端,值插入由序列自动处理

编辑:

我可能错了,但我注意到您创建了一个序列,但没有分配它:

CREATE TABLE computer (id BIGINT NOT NULL, name VARCHAR(255) NOT NULL, introduced TIMESTAMP, discontinued TIMESTAMP, company_id BIGINT, CONSTRAINT pk_computer PRIMARY KEY (id));
CREATE SEQUENCE computer_seq START WITH 1000;
Postgres
中,您创建序列,然后按如下方式分配它们:

create table users (
  id  bigint not null
);

create sequence users_seq;
alter table users alter column id set default nextval('users_seq');
H2
中,据我所知,这是分配自动增量的方式:

create table test(id bigint auto_increment, name varchar(255));

采取形式。

据我所知,这不是一个容易解决的问题,但您的DDL语句没有指定H2的自动增量。检查示例项目的play slick SQL代码:


还要检查H2文档:

我不想碰它,因为它是由Slick自动生成的。当然,应该有一种更一致的方法来做到这一点。我添加了一些可能相关的内容。create查询不是我写的,它取自此示例:另一件事是,如果一个列具有自动递增功能,则slick代码生成器会向字段添加一个
O.AutoInc
,您的id列应该看起来像
val id:column[Long]=列[Long](“ID”,O.PrimaryKey,O.AutoInc)
至少在Postgres中是这样,不幸的是我不是
H2
用户,我无法进一步帮助您,如果AutoInc使用纯SQL工作,您可能可以尝试,例如执行一些插入。另外,要插入的sql语句具有
(为计算机选择下一个值)
,它从序列中手动选择下一个值并将其用作id。
create table test(id bigint auto_increment, name varchar(255));