Java H2索引名唯一性

Java H2索引名唯一性,java,hibernate,jpa,orm,h2,Java,Hibernate,Jpa,Orm,H2,我对h2数据库中索引名的唯一性有一个小问题。使用mysql/mariadb,可以同时为表A和表B定义名为“X”的索引。对于h2数据库,这是不可能的,因为每个数据库的索引名称应该是唯一的 这对我来说是个问题,因为我有一个定义了以下属性的基本JPA实体类: @org.hibernate.annotations.Index(name = "X") protected String x; 它由类别A和B继承,类别B的索引创建失败,出现以下错误: ERROR [main] o.h.tool.hbm2dd

我对h2数据库中索引名的唯一性有一个小问题。使用mysql/mariadb,可以同时为表A和表B定义名为“X”的索引。对于h2数据库,这是不可能的,因为每个数据库的索引名称应该是唯一的

这对我来说是个问题,因为我有一个定义了以下属性的基本JPA实体类:

@org.hibernate.annotations.Index(name = "X")
protected String x;
它由类别A和B继承,类别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创建一个适配器,以表名作为此类索引名的前缀?

尽管您应该始终拥有并使用FlywayDB迁移架构版本,但您可以根据需要覆盖@index

我加了一个例子来证明这一点

这些类如下所示:

@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)
架构是这样生成的:

@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)
这样:

  • 在域模型中保留基类属性(字段、getter和setter)
  • 每个表都有自己的
    x
    列和相关索引
  • 问题是基类中不能有字段,因为Hibernate将尝试创建它两次。您可以在Hibernate上提交Jira问题,并提到HBM模式生成应该跳过索引(如果已经创建了索引)


    最优雅的解决方案是简单地使用适当的数据库模式,并删除HBM-DDL模式生成。

    看起来您运气不好。我也会小心地将索引定义为注释。它们更容易分开处理。这是我所期望的。谢谢!