H2索引名称唯一性
H2 index name uniqueness
我对 h2 数据库中索引名称的唯一性有一个小问题。使用 mysql/mariadb 可以同时为 table A 和 table B 定义名为 "X" 的索引。使用 h2 数据库是不可能的,因为每个数据库的索引名称应该是唯一的。
这对我来说是个问题,因为我有一个基础 JPA 实体 class,其中定义了以下 属性:
@org.hibernate.annotations.Index(name = "X")
protected String x;
它由 class A 和 B 继承,class B 的索引创建失败并出现以下错误:
ERROR [main] o.h.tool.hbm2ddl.SchemaUpdate - HHH000388: Unsuccessful: create index X on B(x)
ERROR [main] o.h.tool.hbm2ddl.SchemaUpdate - Index "X" already exists
是否可以告诉 hibernate 自动创建索引名称或以某种方式为 H2 创建一个适配器,为这些索引名称添加 table 个名称前缀?
尽管您应该始终拥有 database drive the schema evolution 并使用 FlywayDB 来迁移架构版本,但您可以根据需要覆盖 @Index。
我加了一个test on GitHub来证明这一点
classes 看起来像这样:
@Entity(name = "Base")
@Table(name="Base")
@Inheritance(strategy = InheritanceType.JOINED)
public static abstract class Base {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Transient
protected String x;
public Long getId() {
return id;
}
public String getX() {
return x;
}
public void setX(String x) {
this.x = x;
}
}
@Entity(name = "ChildY")
@Table(name="ChildY")
@DiscriminatorValue("Y")
public static class ChildY extends Base {
private String y;
@Override
@org.hibernate.annotations.Index(name = "xy")
@Access(AccessType.PROPERTY)
public String getX() {
return x;
}
}
@Entity(name = "ChildZ")
@Table(name="ChildZ")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorValue("Z")
public static class ChildZ extends Base {
private String z;
@Override
@org.hibernate.annotations.Index(name = "xz")
@Access(AccessType.PROPERTY)
public String getX() {
return x;
}
}
模式生成如下:
create table Base (id bigint generated by default as identity (start with 1), primary key (id))
create table ChildY (x varchar(255), y varchar(255), id bigint not null, primary key (id))
create table ChildZ (x varchar(255), z varchar(255), id bigint not null, primary key (id))
create index xy on ChildY (x)
create index xz on ChildZ (x)
这样:
- 您在域模型中保留基础 class 属性(字段,getter 和 setter)
- 每个 table 都有自己的
x
列和关联的索引
问题是您不能在基 class 中拥有该字段,因为 Hibernate 将尝试创建它两次。您可以在 Hibernate 上提交 Jira 问题并提及 HBM 模式生成应该跳过索引(如果它已经创建)。
最优雅的解决方案是简单地使用适当的数据库模式并删除 HBM-DDL 模式生成。
我对 h2 数据库中索引名称的唯一性有一个小问题。使用 mysql/mariadb 可以同时为 table A 和 table B 定义名为 "X" 的索引。使用 h2 数据库是不可能的,因为每个数据库的索引名称应该是唯一的。
这对我来说是个问题,因为我有一个基础 JPA 实体 class,其中定义了以下 属性:
@org.hibernate.annotations.Index(name = "X")
protected String x;
它由 class A 和 B 继承,class B 的索引创建失败并出现以下错误:
ERROR [main] o.h.tool.hbm2ddl.SchemaUpdate - HHH000388: Unsuccessful: create index X on B(x)
ERROR [main] o.h.tool.hbm2ddl.SchemaUpdate - Index "X" already exists
是否可以告诉 hibernate 自动创建索引名称或以某种方式为 H2 创建一个适配器,为这些索引名称添加 table 个名称前缀?
尽管您应该始终拥有 database drive the schema evolution 并使用 FlywayDB 来迁移架构版本,但您可以根据需要覆盖 @Index。
我加了一个test on GitHub来证明这一点
classes 看起来像这样:
@Entity(name = "Base")
@Table(name="Base")
@Inheritance(strategy = InheritanceType.JOINED)
public static abstract class Base {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Transient
protected String x;
public Long getId() {
return id;
}
public String getX() {
return x;
}
public void setX(String x) {
this.x = x;
}
}
@Entity(name = "ChildY")
@Table(name="ChildY")
@DiscriminatorValue("Y")
public static class ChildY extends Base {
private String y;
@Override
@org.hibernate.annotations.Index(name = "xy")
@Access(AccessType.PROPERTY)
public String getX() {
return x;
}
}
@Entity(name = "ChildZ")
@Table(name="ChildZ")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorValue("Z")
public static class ChildZ extends Base {
private String z;
@Override
@org.hibernate.annotations.Index(name = "xz")
@Access(AccessType.PROPERTY)
public String getX() {
return x;
}
}
模式生成如下:
create table Base (id bigint generated by default as identity (start with 1), primary key (id))
create table ChildY (x varchar(255), y varchar(255), id bigint not null, primary key (id))
create table ChildZ (x varchar(255), z varchar(255), id bigint not null, primary key (id))
create index xy on ChildY (x)
create index xz on ChildZ (x)
这样:
- 您在域模型中保留基础 class 属性(字段,getter 和 setter)
- 每个 table 都有自己的
x
列和关联的索引
问题是您不能在基 class 中拥有该字段,因为 Hibernate 将尝试创建它两次。您可以在 Hibernate 上提交 Jira 问题并提及 HBM 模式生成应该跳过索引(如果它已经创建)。
最优雅的解决方案是简单地使用适当的数据库模式并删除 HBM-DDL 模式生成。