Angeben eines Index (nicht eindeutiger Schlüssel) mithilfe von JPA

98

Wie definieren Sie ein Feld, z. B. emailals Index mit JPA-Anmerkungen? Wir benötigen einen nicht eindeutigen Schlüssel, emailda in diesem Feld buchstäblich Millionen von Abfragen pro Tag ausgeführt werden und es ohne den Schlüssel etwas langsam ist.

@Entity
@Table(name="person", 
       uniqueConstraints=@UniqueConstraint(columnNames={"code", "uid"}))
public class Person {
    // Unique on code and uid
    public String code;
    public String uid;

    public String username;
    public String name;
    public String email;
}

Ich habe eine Annotation im Ruhezustand gesehen, aber ich versuche, herstellerspezifische Lösungen zu vermeiden, da wir uns immer noch zwischen Ruhezustand und Datenkern entscheiden.

AKTUALISIEREN:

Ab JPA 2.1 können Sie dies tun. Siehe: Die Anmerkung @Index ist für diesen Speicherort nicht zulässig

Jacob
quelle
6
Ich wäre großartig, wenn Sie die Antwort aktualisieren könnten, damit die Leute feststellen, dass es mit JPA 2.1 wirklich einen Weg gibt, dies zu tun
Borjab
2
Warum akzeptierst du nicht die am besten bewertete Antwort?
NaXa

Antworten:

206

Mit JPA 2.1 sollten Sie dazu in der Lage sein.

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table;

@Entity
@Table(name = "region",
       indexes = {@Index(name = "my_index_name",  columnList="iso_code", unique = true),
                  @Index(name = "my_index_name2", columnList="name",     unique = false)})
public class Region{

    @Column(name = "iso_code", nullable = false)
    private String isoCode;

    @Column(name = "name", nullable = false)
    private String name;

} 

Update : Wenn Sie jemals zwei oder mehr Spalten erstellen und indizieren müssen, können Sie Kommas verwenden. Beispielsweise:

@Entity
@Table(name    = "company__activity", 
       indexes = {@Index(name = "i_company_activity", columnList = "activity_id,company_id")})
public class CompanyActivity{
Borjab
quelle
Vielen Dank an Alvin für seine Antwort. (+1 Stimme). Aber ich musste nach ein paar Dingen suchen und ich hoffe, dass dieses Beispiel Ihr Leben leichter macht
Borjab
Genau das, wonach ich gesucht habe - ein einfacher und sauberer Code -, der nicht nur das Ganze beschreibt. Danke +1.
DominikAngerer
2
@borjab - können Sie mir bitte einen Hinweis geben, wo ich ein "offizielles" Beispiel oder eine Spezifikation für die Verwendung der @IndexAnmerkung in der @TableAnmerkung finden kann? Ich habe nach JSR 338 gesucht, aber dort nicht gefunden. Ihr Beitrag ist sehr nützlich für mich.
JimHawkins
2
@ Ulrich Nicht gerade die offizielle Dokumentation, aber Orakel Blog blogs.oracle.com/arungupta/entry/jpa_2_1_schema_generation
Borjab
Ich frage mich, ob eine Spalte mit @Column (unique = true) mit der Indexliste zusammengeführt wird (da unique auch ein Index ist).
wkrueger
34

Eine einzigartige handverlesene Sammlung von Indexanmerkungen

= Technische Daten =

= ORM Frameworks =

= ORM für Android =

= Andere (schwer zu kategorisieren) =

  • Realm - Alternative DB für iOS / Android: Anmerkung io.realm.annotations.Index;
  • Empire-db - eine leichte und dennoch leistungsstarke relationale DB-Abstraktionsschicht, die auf JDBC basiert. Es gibt keine Schemadefinition durch Anmerkungen.
  • Kotlin NoSQL (GitHub) - ein reaktives und typsicheres DSL für die Arbeit mit NoSQL-Datenbanken (PoC): ???
  • Slick - Reactive Functional Relational Mapping für Scala. Es gibt keine Schemadefinition durch Anmerkungen.

Gehen Sie einfach für einen von ihnen.

naXa
quelle
31

JPA 2.1 bietet (endlich) Unterstützung für Indizes und Fremdschlüssel! Weitere Informationen finden Sie in diesem Blog . JPA 2.1 ist ein Teil von Java EE 7, das nicht verfügbar ist.

Wenn Sie gerne am Rande leben, können Sie den neuesten Snapshot für Eclipselink aus dem Maven-Repository abrufen (groupId: org.eclipse.persistence, artefaktId: eclipselink, Version: 2.5.0-SNAPSHOT). Verwenden Sie nur für die JPA-Annotationen (die mit jedem Anbieter funktionieren sollten, sobald dieser 2.1 unterstützt) die Artefakt-ID: javax.persistence, Version: 2.1.0-SNAPSHOT.

Ich verwende es für ein Projekt, das erst nach seiner Veröffentlichung abgeschlossen wird, und ich habe keine schrecklichen Probleme bemerkt (obwohl ich nichts zu komplexes damit mache).

UPDATE (26. September 2013): Heutzutage sind Release- und Release Candidate-Versionen von Eclipselink im zentralen (Haupt-) Repository verfügbar, sodass Sie das Eclipselink-Repository in Maven-Projekten nicht mehr hinzufügen müssen. Die neueste Release-Version ist 2.5.0, aber auch 2.5.1-RC3 ist vorhanden. Ich würde wegen Problemen mit der Version 2.5.0 so schnell wie möglich auf 2.5.1 umsteigen (das modelgen-Zeug funktioniert nicht).

Alvin Thompson
quelle
9

In JPA 2.1 müssen Sie Folgendes tun

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.Table;

@Entity(name="TEST_PERSON")
@Table(
    name="TEST_PERSON", 
    indexes = {
       @Index(name = "PERSON_INDX_0", columnList = "age"),
       @Index(name = "PERSON_INDX_1", columnList = "fName"),
       @Index(name = "PERSON_INDX_1", columnList = "sName")  })
public class TestPerson {

    @Column(name = "age", nullable = false)
    private int age;

    @Column(name = "fName", nullable = false)
    private String firstName;

    @Column(name = "sName", nullable = false)
    private String secondName;

    @Id
    private long id;

    public TestPerson() {
    }
}

Im obigen Beispiel hat die Tabelle TEST_PERSON 3 Indizes:

  • eindeutiger Index für die Primärschlüssel-ID

  • Index auf Alter

  • zusammengesetzter Index auf FNAME, SNAME

Hinweis 1: Sie erhalten den zusammengesetzten Index, indem Sie zwei @ Index-Annotationen mit demselben Namen haben

Hinweis 2: Sie geben den Spaltennamen in der Spaltenliste an, nicht den Feldnamen

James Clayton
quelle
5

Ich würde wirklich gerne in der Lage sein, Datenbankindizes auf standardisierte Weise anzugeben, aber leider ist dies nicht Teil der JPA-Spezifikation (möglicherweise, weil die JPA-Spezifikation keine Unterstützung für die DDL-Generierung erfordert, was eine Art Straßensperre für ist eine solche Funktion).

Dafür müssen Sie sich auf eine anbieterspezifische Erweiterung verlassen. Hibernate, OpenJPA und EclipseLink bieten eindeutig eine solche Erweiterung. Ich kann DataNucleus nicht bestätigen, aber da die Indexdefinition Teil von JDO ist, denke ich, dass dies der Fall ist.

Ich hoffe wirklich, dass die Indexunterstützung in den nächsten Versionen der Spezifikation standardisiert wird und daher irgendwie nicht mit anderen Antworten übereinstimmt. Ich sehe keinen guten Grund, so etwas nicht in JPA aufzunehmen (zumal die Datenbank nicht immer unter Ihrer Kontrolle steht). für optimale Unterstützung der DDL-Generierung.

Ich schlage übrigens vor, die JPA 2.0-Spezifikation herunterzuladen.

Pascal Thivent
quelle
4

Soweit ich weiß, gibt es keine JPA-Provider-übergreifende Möglichkeit, Indizes anzugeben. Sie können sie jedoch jederzeit von Hand direkt in der Datenbank erstellen. Die meisten Datenbanken übernehmen sie automatisch während der Abfrageplanung.

Tassos Bassoukos
quelle
2
lol, das setzt voraus, dass Sie DBAs haben, die die Arbeit eines DBAs erledigen (:
Jacob
3
Ich finde es etwas seltsam, dass es eine Möglichkeit gibt, "einzigartig" zu machen, aber keine Möglichkeit, einen Index zu erstellen.
Jacob
7
@Jacob - Nun, es ist wichtig zu wissen, ob ein Feld eindeutig ist oder nicht. Indizes dienen dagegen der Optimierung des Datenbankzugriffs. Soweit ich sehe, muss nicht bekannt sein, ob eine Spalte ein Index auf der Java-Ebene ist oder nicht. Wie Sie sagten, kann der DBA einen Index einrichten, wenn es den Anschein hat, dass eine bestimmte Spalte davon profitieren würde.
Java Drinker
1
@Jacob, es gibt keine Indexunterstützung, da dies lediglich eine Optimierung ist (normalerweise eine wichtige, aber immer noch eine Optimierung). OTOH, ob ein Feld (oder eine Reihe von Feldern) eindeutig ist oder nicht, hängt vom Modell ab und beeinträchtigt die Korrektheit. Da kein vollwertiger DBA mit 200 USD / Std. Erforderlich ist, reichen normalerweise einige einfache Anweisungen zur Indexerstellung aus.
Tassos Bassoukos
8
JPA 2.1 spezifiziertjavax.persistence.Index
Lukas Eder
2

EclipseLink hat eine Anmerkung (z. B. @Index ) bereitgestellt , um einen Index für Spalten zu definieren. Es gibt ein Beispiel für seine Verwendung. Ein Teil des Beispiels ist enthalten ...

Die Felder firstName und lastName werden zusammen und einzeln indiziert.

@Entity
@Index(name="EMP_NAME_INDEX", columnNames={"F_NAME","L_NAME"})  // Columns indexed together
public class Employee{
    @Id
    private long id;

    @Index                      // F_NAME column indexed
    @Column(name="F_NAME")
    private String firstName;

    @Index                      // L_NAME column indexed
    @Column(name="L_NAME")
    private String lastName;
    ...
}
Nathan
quelle
1

Mit OpenJPA können Sie nicht standardmäßige Anmerkungen angeben, um den Index für die Eigenschaft zu definieren.

Details finden Sie hier .

Experte
quelle
0

Dies ist mit der JPA-Annotation nicht möglich. Und das ist sinnvoll: Wenn eine UniqueConstraint Geschäftsregeln klar definiert, ist ein Index nur eine Möglichkeit, die Suche zu beschleunigen. Das sollte also wirklich von einem DBA gemacht werden.

Thierry-Dimitri Roy
quelle
0

Diese Lösung ist für EclipseLink 2.5 und funktioniert (getestet):

@Table(indexes = {@Index(columnList="mycol1"), @Index(columnList="mycol2")})
@Entity
public class myclass implements Serializable{
      private String mycol1;
      private String mycol2;
}

Dies setzt eine aufsteigende Reihenfolge voraus.

Joe Almore
quelle