web-dev-qa-db-fra.com

Spécification d'un index (clé non unique) à l'aide de JPA

Comment définissez-vous un champ, par exemple email comme ayant un index utilisant des annotations JPA. Nous avons besoin d'une clé non unique sur email car il y a littéralement des millions de requêtes sur ce champ par jour, et c'est un peu lent sans la clé.

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

J'ai vu une annotation spécifique à la mise en veille prolongée, mais j'essaie d'éviter les solutions spécifiques au fournisseur, car nous sommes toujours en train de décider entre la mise en veille prolongée et le datanucleus.

MISE À JOUR:

À partir de JPA 2.1, vous pouvez le faire. Voir: L'annotation @Index n'est pas autorisée pour cet emplacement

82
Jacob

Autant que je sache, il n'existe pas de méthode inter-fournisseur JPA permettant de spécifier des index. Cependant, vous pouvez toujours les créer à la main directement dans la base de données. La plupart des bases de données les récupéreront automatiquement lors de la planification des requêtes.

4
Tassos Bassoukos

Avec JPA 2.1, vous devriez pouvoir le faire.

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;

} 

Mise à jour: Si vous avez besoin de créer et d’indexer au moins deux colonnes, vous pouvez utiliser des virgules. Par exemple:

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

JPA 2.1 (enfin) ajoute le support pour les index et les clés étrangères! Voir ce blog pour plus de détails. JPA 2.1 fait partie de Java EE 7, qui est sorti.

Si vous aimez vivre sur Edge, vous pouvez obtenir le dernier instantané pour eclipselink à partir de leur référentiel maven (groupId: org.Eclipse.persistence, artifactId: eclipselink, version: 2.5.0-SNAPSHOT). Pour les annotations JPA uniquement (qui devraient fonctionner avec tout fournisseur une fois qu'ils ont pris en charge la version 2.1), utilisez artifactID: javax.persistence, version: 2.1.0-SNAPSHOT.

Je l'utilise pour un projet qui ne sera pas terminé avant sa sortie, et je n'ai pas remarqué d'horribles problèmes (bien que je ne fasse rien de trop complexe avec cela).

MISE À JOUR (26 septembre 2013): Les versions actuelles et potentielles d'eclipselink sont désormais disponibles dans le référentiel central (principal). Vous n'avez donc plus besoin d'ajouter le référentiel eclipselink dans les projets Maven. La dernière version est la 2.5.0 mais la version 2.5.1-RC3 est également présente. Je passerais à la version 2.5.1 dès que possible en raison de problèmes avec la version 2.5.0 (les commandes de modelgen ne fonctionnent pas).

30
Alvin Thompson

Dans JPA 2.1, vous devez effectuer les opérations suivantes.

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

Dans l'exemple ci-dessus, la table TEST_PERSON aura 3 index:

  • index unique sur l'ID de clé primaire

  • index sur AGE

  • index composé sur FNAME, SNAME

Remarque 1: vous obtenez l'index composé en ayant deux annotations @Index du même nom.

Remarque 2: vous spécifiez le nom de la colonne dans la liste de colonnes, pas le nom de champ.

8
James Clayton

J'aimerais vraiment pouvoir spécifier les index de base de données de manière standardisée, mais malheureusement, cela ne fait pas partie de la spécification JPA (peut-être parce que la génération DDL n'est pas requise par la spécification JPA, qui est une sorte de blocage pour une telle caractéristique).

Vous devrez donc vous en remettre à une extension spécifique du fournisseur. Hibernate, OpenJPA et EclipseLink offrent clairement une telle extension. Je ne peux pas confirmer pour DataNucleus, mais comme la définition des index fait partie de JDO, je suppose que oui.

J'espère vraiment que le support d'index sera normalisé dans les prochaines versions de la spécification et donc en désaccord avec d'autres réponses, je ne vois aucune raison de ne pas inclure une telle chose dans JPA (d'autant plus que la base de données n'est pas toujours sous votre contrôle) pour une prise en charge optimale de la génération DDL.

En passant, je suggère de télécharger la spécification JPA 2.0.

5
Pascal Thivent

EclipseLink a fourni une annotation (par exemple, @ Index ) pour définir un index sur des colonnes. Il existe un exemple de son utilisation. Une partie de l'exemple est incluse ...

Les champs firstName et lastName sont indexés ensemble et individuellement.

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

Pour résumer les autres réponses:

Je voudrais juste aller pour l'un d'eux. Quoi qu'il en soit, cela viendra de toute façon avec JPA 2.1 et ne devrait pas être trop difficile à changer si vous voulez vraiment changer de fournisseur JPA.

1
Jack

OpenJPA vous permet de spécifier des annotations non standard pour définir un index sur une propriété.

Les détails sont ici .

1
expert

Cette solution est pour EclipseLink 2.5, et cela fonctionne (testé):

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

Cela suppose un ordre ascendant.

0
Joe Almore

Il n'est pas possible de faire cela en utilisant une annotation JPA. Et cela a du sens: lorsqu'un UniqueConstraint définit clairement une règle de gestion, un index n’est qu’un moyen d’accélérer les recherches. Donc, cela devrait vraiment être fait par un DBA.

0