Specifica di un indice (chiave non univoca) utilizzando JPA


98

Come si definisce un campo, ad esempio emailse ha un indice utilizzando le annotazioni JPA. Abbiamo bisogno di una chiave non univoca emailperché ci sono letteralmente milioni di query su questo campo al giorno, ed è un po 'lento senza la chiave.

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

Ho visto un'annotazione specifica di ibernazione ma sto cercando di evitare soluzioni specifiche del fornitore poiché stiamo ancora decidendo tra ibernazione e datanucleus.

AGGIORNARE:

A partire da JPA 2.1, puoi farlo. Vedere: L'annotazione @Index non è consentita per questa posizione


6
Sarei fantastico se potessi aggiornare la risposta in modo che le persone
scoprano

2
Perché non accetti la risposta più votata?
naXa

Risposte:


206

Con JPA 2.1 dovresti essere in grado di farlo.

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;

} 

Aggiornamento : se hai bisogno di creare e indicizzare con due o più colonne, puoi usare le virgole. Per esempio:

@Entity
@Table(name    = "company__activity", 
       indexes = {@Index(name = "i_company_activity", columnList = "activity_id,company_id")})
public class CompanyActivity{

Grazie ad Alvin per la sua risposta. (+1 voto). Ma ho dovuto cercare alcune cose e spero che questo esempio possa semplificarti la vita
borjab

Esattamente quello che stavo cercando - un codice semplice e pulito tagliato - non solo descrivendo l'intera cosa. Grazie +1.
DominikAngerer

2
@borjab - puoi darmi un suggerimento dove posso trovare un esempio o una specifica "ufficiale" per l'utilizzo @Indexdell'annotazione all'interno @Tabledell'annotazione? Ho cercato su JSR 338 ma non l'ho trovato lì. Il tuo post mi è molto utile.
JimHawkins

2
@Ulrich Non esattamente la documentatio ufficiale ma oracle blog blogs.oracle.com/arungupta/entry/jpa_2_1_schema_generation
borjab

Mi chiedo, se ho una colonna con @Column (unique = true), viene unita all'elenco degli indici (poiché unico è anche un indice)?
wkrueger

34

Una raccolta unica selezionata a mano di annotazioni dell'indice

= Specifiche =

= Framework ORM =

= ORM per Android =

= Altro (difficile da classificare) =

  • Regno - DB alternativo per iOS / Android: Annotazione io.realm.annotations.Index;
  • Empire-db : un livello di astrazione DB relazionale leggero ma potente basato su JDBC. Non ha una definizione dello schema tramite annotazioni;
  • Kotlin NoSQL (GitHub) - un DSL reattivo e indipendente dai tipi per lavorare con database NoSQL (PoC): ???
  • Slick - Reactive Functional Relational Mapping for Scala. Non ha una definizione dello schema tramite annotazioni.

Scegli uno di loro.


31

JPA 2.1 (finalmente) aggiunge il supporto per indici e chiavi esterne! Vedi questo blog per i dettagli. JPA 2.1 fa parte di Java EE 7, che è uscito.

Se ti piace vivere al limite, puoi ottenere l'ultima istantanea per eclipselink dal loro repository maven (groupId: org.eclipse.persistence, artifactId: eclipselink, versione: 2.5.0-SNAPSHOT). Solo per le annotazioni JPA (che dovrebbero funzionare con qualsiasi provider una volta che supportano 2.1) utilizzare artifactID: javax.persistence, versione: 2.1.0-SNAPSHOT.

Lo sto usando per un progetto che non sarà finito fino a dopo il suo rilascio, e non ho notato problemi orribili (anche se non sto facendo nulla di troppo complesso con esso).

AGGIORNAMENTO (26 settembre 2013): Al giorno d'oggi le versioni release e release candidate di eclipselink sono disponibili nel repository centrale (principale), quindi non è più necessario aggiungere il repository eclipselink nei progetti Maven. L'ultima versione di rilascio è 2.5.0 ma è presente anche 2.5.1-RC3. Passerei alla 2.5.1 al più presto a causa di problemi con la versione 2.5.0 (la roba modelgen non funziona).


9

In JPA 2.1 è necessario eseguire le seguenti operazioni

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() {
    }
}

Nell'esempio sopra la tabella TEST_PERSON avrà 3 indici:

  • indice univoco sull'ID chiave primaria

  • indice su AGE

  • indice composto su FNAME, SNAME

Nota 1: ottieni l'indice composto avendo due annotazioni @Index con lo stesso nome

Nota 2: specificare il nome della colonna in columnList e non in fieldName


5

Mi piacerebbe davvero essere in grado di specificare gli indici del database in modo standardizzato ma, purtroppo, questo non fa parte della specifica JPA (forse perché il supporto della generazione DDL non è richiesto dalla specifica JPA, che è una sorta di blocco stradale per tale caratteristica).

Quindi dovrai fare affidamento su un'estensione specifica del provider per questo. Hibernate, OpenJPA ed EclipseLink offrono chiaramente tale estensione. Non posso confermare per DataNucleus ma poiché la definizione degli indici fa parte di JDO, immagino che lo faccia.

Spero davvero che il supporto dell'indice venga standardizzato nelle prossime versioni delle specifiche e quindi in qualche modo non sono d'accordo con altre risposte, non vedo alcuna buona ragione per non includere una cosa del genere in JPA (soprattutto perché il database non è sempre sotto il tuo controllo) per un supporto ottimale per la generazione di DDL.

A proposito, suggerisco di scaricare le specifiche JPA 2.0.


4

Per quanto ne so, non esiste un modo cross-JPA-Provider per specificare gli indici. Tuttavia, puoi sempre crearli a mano direttamente nel database, la maggior parte dei database li raccoglierà automaticamente durante la pianificazione delle query.


2
lol, questo presuppone che tu abbia DBA che fanno il lavoro di un DBA (:
Jacob

3
Trovo un po 'strano che ci sia un modo per fare "unico" ma non un modo per fare un indice.
Jacob il

7
@Jacob - Beh, è ​​importante sapere a livello di applicazione se un campo sarà unico o meno. Gli indici, d'altra parte, hanno lo scopo di ottimizzare l'accesso al database. Non è necessario (per quanto vedo) sapere se una colonna è un indice o meno a livello java. Come hai detto, il DBA può impostare un indice se sembra che una particolare colonna ne trarrebbe vantaggio.
Bevitore Java il

1
@Jacob, non esiste un supporto per l'indice perché si tratta semplicemente di un'ottimizzazione (di solito importante, ma pur sempre un'ottimizzazione). OTOH se un campo (o un insieme di campi) è unico o meno dipende dal modello e influirà sulla correttezza. Inoltre, non è necessario un DBA completo da 200 USD / ora, di solito sono sufficienti alcune semplici istruzioni per la creazione di indici.
Tassos Bassoukos

8

2

EclipseLink ha fornito un'annotazione (ad esempio @Index ) per definire un indice sulle colonne. C'è un esempio del suo utilizzo. Parte dell'esempio è inclusa ...

I campi firstName e lastName vengono indicizzati, insieme e individualmente.

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

1

OpenJPA consente di specificare un'annotazione non standard per definire l'indice sulla proprietà.

I dettagli sono qui .



0

Non è possibile farlo utilizzando l'annotazione JPA. E questo ha senso: laddove un UniqueConstraint definisce chiaramente le regole aziendali, un indice è solo un modo per rendere la ricerca più veloce. Quindi questo dovrebbe davvero essere fatto da un DBA.


0

Questa soluzione è per EclipseLink 2.5 e funziona (testata):

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

Ciò presuppone un ordine ascendente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.