2015-08-25 7 views
5

Ich habe ein kleines Problem mit der Eindeutigkeit der Indexnamen in der Datenbank h2. Mit mysql/mariadb ist es möglich, den Index "X" für Tabelle A und Tabelle B gleichzeitig zu definieren. Bei der h2-Datenbank ist dies nicht möglich, da der Name des Indexes pro Datenbank eindeutig sein sollte.H2 Index Name Eindeutigkeit

Es ist ein Problem für mich, da ich eine Basis JPA Entity-Klasse mit der folgenden Eigenschaft definiert habe:

@org.hibernate.annotations.Index(name = "X") 
protected String x; 

Es wird von der Klasse A vererbt wird und B und die Indexerstellung nicht für die Klasse B mit dem folgenden Fehler:

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 

Ist es möglich, automatisch Indexnamen erstellen oder irgendwie einen Adapter für H2 zu schaffen, die solche Indexnamen mit Tabellennamen tell winter Präfix wird?

+2

Scheint wie du kein Glück haben. Ich würde vorsichtig sein, die Indizes auch als Anmerkungen zu definieren. Sie sind einfacher separat zu handhaben. – Kayaman

Antwort

2

Obwohl Sie immer die database drive the schema evolution haben und FlywayDB verwenden sollten, um Schemaversionen zu migrieren, können Sie den @Index wie gewünscht überschreiben.

Ich habe eine test on GitHub hinzugefügt, um dies zu beweisen.

Die Klassen wie folgt aussehen:

@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; 
    } 
} 

Das Schema wie folgt generiert:

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) 

Auf diese Weise:

  1. Sie behalten die Basisklasse Eigenschaft in der Domain Model (Feld, Getter und Setter)
  2. Jede Tabelle erhält ihren eigenen x Spalt mit einem zugehörigen Index

Das Problem ist, dass Sie nicht das Feld in der Basisklasse haben können, wie Hibernate es versucht zweimal zu erstellen. Sie können ein Jira-Problem bei Hibernate absetzen und erwähnen, dass die HBM-Schema-Generierung den Index überspringen sollte, wenn er bereits erstellt wurde.

Die eleganteste Lösung besteht darin, einfach ein geeignetes Datenbankschema zu verwenden und die HBM-DDL-Schema-Generierung zu entfernen.

+1

Das habe ich erwartet. Danke vielmals! – Konrad