如何使用生成的索引将实体对象保存到已初始化的 h2 table 中?
How to save an Entity object into an initialized h2 table with generated index?
我有一个带有 h2 数据库的 spring 引导项目。 A table debug
从 schema.sql
:
初始化
DROP TABLE IF EXISTS debug;
CREATE TABLE debug (
id BIGINT PRIMARY KEY,
dummycol VARCHAR(250) NOT NULL
);
data.sql
:
INSERT INTO debug (id, dummycol) VALUES
(0, 'foo'),
(1, 'ba');
为此,我必须将 spring.jpa.hibernate.ddl-auto=none
放入 application.properties。根据 documentation 这是 schema.sql
所必需的,但我发现在生成模式时使用另一个值,例如 create-drop
(我从带注释的 classes 假设)加载脚本 data.sql
被忽略,因此 table 在启动后为空。
我定义了一个实体class:
@Entity
@Table(name = "debug")
@Data
@NoArgsConstructor
public class DebugE {
@Id
//@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="id")
private Long id;
@Column(name="dummycol")
private String dummy;
}
然后,我 subclass CrudRepository
: public interface DebugRepository extends CrudRepository<DebugE, Long>
并将实体对象添加到 table
@Autowired
DebugRepository cr;
...
DebugE d = new DebugE();
d.setId(computeFreeId(cr))
d.setDummy("foo1");
cr.save(d);
到目前为止一切正常,但现在我想 id
自动设置。
为此,我将 @GeneratedValue
添加到 class 并注释掉 d.setId
,因为我希望框架为我做这件事。我对 GenerationType
没有偏好,到目前为止都不起作用:
AUTO
,SEQUENCE
:
o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 90036, SQLState: 90036
o.h.engine.jdbc.spi.SqlExceptionHelper : Sequence "HIBERNATE_SEQUENCE" not found; SQL statement:
call next value for hibernate_sequence [90036-200]
o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [call next value for hibernate_sequence]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement] with root cause
org.h2.jdbc.JdbcSQLSyntaxErrorException: Sequence "HIBERNATE_SEQUENCE" not found; SQL statement:
call next value for hibernate_sequence [90036-200]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:576) ~[h2-1.4.200.jar:1.4.200]
IDENTITY
:
o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 23502, SQLState: 23502
o.h.engine.jdbc.spi.SqlExceptionHelper : NULL not allowed for column "ID"; SQL statement:
insert into debug (id, dummycol) values (null, ?) [23502-200]
o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: NULL not allowed for column "ID"; SQL statement:
insert into debug (id, dummycol) values (null, ?) [23502-200]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:459) ~[h2-1.4.200.jar:1.4.200]
TABLE
:
o.hibernate.id.enhanced.TableGenerator : HHH000351: Could not read or init a hi value
org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "HIBERNATE_SEQUENCES" not found; SQL statement:
select tbl.next_val from hibernate_sequences tbl where tbl.sequence_name=? for update [42102-200]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:453) ~[h2-1.4.200.jar:1.4.200]
基于其他问题的尝试:
strategy=GenerationType.IDENTITY
并将 hibernate.dialect=org.hibernate.dialect.H2Dialect
添加到 application.properties
。
发出警告:'hibernate.dialect' is an unknown property.
并且错误消息没有变化
-
添加
spring.jpa.hibernate.use-new-id-generator-mappings=false
IDENTITY
、SEQUENCE
没有变化。
TABLE
的类似错误:
org.hibernate.orm.deprecation : HHH90000015: Found use of deprecated [org.hibernate.id.MultipleHiLoPerTableGenerator] table-based id generator; use org.hibernate.id.enhanced.TableGenerator instead. See Hibernate Domain Model Mapping Guide for details.
o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 42102, SQLState: 42S02
o.h.engine.jdbc.spi.SqlExceptionHelper : Table "HIBERNATE_SEQUENCES" not found; SQL statement:
select sequence_next_hi_value from hibernate_sequences where sequence_name = 'debug' for update [42102-200]
将 spring.jpa.hibernate.ddl-auto
从 none
设置为 create-drop
有效(即生成 ID,将行添加到 table)但现在 table 不再从 data.sql
.
其他详细信息
application.properties
:
spring.datasource.url=jdbc:h2:mem:h2db
spring.h2.console.enabled=true
spring.h2.console.path=/h2
#spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.ddl-auto=create-drop
spring.datasource.initialization-mode=embedded
#hibernate.dialect=org.hibernate.dialect.H2Dialect
#spring.jpa.hibernate.use-new-id-generator-mappings=false
build.gradle
:
plugins {
id 'org.springframework.boot' version '2.3.3.RELEASE'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'java'
id "io.freefair.lombok" version "5.2.1"
}
group = 'com.my.project'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'
}
解决方案
spring.jpa.hibernate.ddl-auto=none
在 application.properties
@GeneratedValue(strategy=GenerationType.IDENTITY)
在 class 和
id BIGINT PRIMARY KEY AUTO_INCREMENT
在 schema.sql 中实现了它。
如果你想生成id同时使用*sql文件,你需要在创建时定义auto_increment 属性到你的id字段table.
因为当你使用生成策略 - Identity 时,hibernate 认为你的列在 table 一侧是自动递增的。
我有一个带有 h2 数据库的 spring 引导项目。 A table debug
从 schema.sql
:
DROP TABLE IF EXISTS debug;
CREATE TABLE debug (
id BIGINT PRIMARY KEY,
dummycol VARCHAR(250) NOT NULL
);
data.sql
:
INSERT INTO debug (id, dummycol) VALUES
(0, 'foo'),
(1, 'ba');
为此,我必须将 spring.jpa.hibernate.ddl-auto=none
放入 application.properties。根据 documentation 这是 schema.sql
所必需的,但我发现在生成模式时使用另一个值,例如 create-drop
(我从带注释的 classes 假设)加载脚本 data.sql
被忽略,因此 table 在启动后为空。
我定义了一个实体class:
@Entity
@Table(name = "debug")
@Data
@NoArgsConstructor
public class DebugE {
@Id
//@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="id")
private Long id;
@Column(name="dummycol")
private String dummy;
}
然后,我 subclass CrudRepository
: public interface DebugRepository extends CrudRepository<DebugE, Long>
并将实体对象添加到 table
@Autowired
DebugRepository cr;
...
DebugE d = new DebugE();
d.setId(computeFreeId(cr))
d.setDummy("foo1");
cr.save(d);
到目前为止一切正常,但现在我想 id
自动设置。
为此,我将 @GeneratedValue
添加到 class 并注释掉 d.setId
,因为我希望框架为我做这件事。我对 GenerationType
没有偏好,到目前为止都不起作用:
AUTO
,SEQUENCE
:
o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 90036, SQLState: 90036
o.h.engine.jdbc.spi.SqlExceptionHelper : Sequence "HIBERNATE_SEQUENCE" not found; SQL statement:
call next value for hibernate_sequence [90036-200]
o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [call next value for hibernate_sequence]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement] with root cause
org.h2.jdbc.JdbcSQLSyntaxErrorException: Sequence "HIBERNATE_SEQUENCE" not found; SQL statement:
call next value for hibernate_sequence [90036-200]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:576) ~[h2-1.4.200.jar:1.4.200]
IDENTITY
:
o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 23502, SQLState: 23502
o.h.engine.jdbc.spi.SqlExceptionHelper : NULL not allowed for column "ID"; SQL statement:
insert into debug (id, dummycol) values (null, ?) [23502-200]
o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: NULL not allowed for column "ID"; SQL statement:
insert into debug (id, dummycol) values (null, ?) [23502-200]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:459) ~[h2-1.4.200.jar:1.4.200]
TABLE
:
o.hibernate.id.enhanced.TableGenerator : HHH000351: Could not read or init a hi value
org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "HIBERNATE_SEQUENCES" not found; SQL statement:
select tbl.next_val from hibernate_sequences tbl where tbl.sequence_name=? for update [42102-200]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:453) ~[h2-1.4.200.jar:1.4.200]
基于其他问题的尝试:
strategy=GenerationType.IDENTITY
并将hibernate.dialect=org.hibernate.dialect.H2Dialect
添加到application.properties
。 发出警告:'hibernate.dialect' is an unknown property.
并且错误消息没有变化-
添加
spring.jpa.hibernate.use-new-id-generator-mappings=false
IDENTITY
、SEQUENCE
没有变化。TABLE
的类似错误:
org.hibernate.orm.deprecation : HHH90000015: Found use of deprecated [org.hibernate.id.MultipleHiLoPerTableGenerator] table-based id generator; use org.hibernate.id.enhanced.TableGenerator instead. See Hibernate Domain Model Mapping Guide for details.
o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 42102, SQLState: 42S02
o.h.engine.jdbc.spi.SqlExceptionHelper : Table "HIBERNATE_SEQUENCES" not found; SQL statement:
select sequence_next_hi_value from hibernate_sequences where sequence_name = 'debug' for update [42102-200]
将spring.jpa.hibernate.ddl-auto
从none
设置为create-drop
有效(即生成 ID,将行添加到 table)但现在 table 不再从data.sql
.
其他详细信息
application.properties
:
spring.datasource.url=jdbc:h2:mem:h2db
spring.h2.console.enabled=true
spring.h2.console.path=/h2
#spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.ddl-auto=create-drop
spring.datasource.initialization-mode=embedded
#hibernate.dialect=org.hibernate.dialect.H2Dialect
#spring.jpa.hibernate.use-new-id-generator-mappings=false
build.gradle
:
plugins {
id 'org.springframework.boot' version '2.3.3.RELEASE'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'java'
id "io.freefair.lombok" version "5.2.1"
}
group = 'com.my.project'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'
}
解决方案
spring.jpa.hibernate.ddl-auto=none
在 application.properties
@GeneratedValue(strategy=GenerationType.IDENTITY)
在 class 和
id BIGINT PRIMARY KEY AUTO_INCREMENT
在 schema.sql 中实现了它。
如果你想生成id同时使用*sql文件,你需要在创建时定义auto_increment 属性到你的id字段table.
因为当你使用生成策略 - Identity 时,hibernate 认为你的列在 table 一侧是自动递增的。