Especificación de un índice (clave no única) mediante JPA

¿Cómo se define un campo, por ejemplo, el email que tiene un índice que utiliza anotaciones JPA? Necesitamos una clave no única en el email porque hay literalmente millones de consultas en este campo por día, y es un poco lento sin la clave.

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

He visto una anotación específica de hibernación, pero estoy tratando de evitar soluciones específicas del vendedor, ya que aún estamos decidiendo entre hibernate y datanucleus.

ACTUALIZAR:

A partir de JPA 2.1, puedes hacer esto. Ver: la anotación @Index no está permitida para esta ubicación

Por lo que yo sé, no hay una forma cruzada de proveedor de JPA para especificar índices. Sin embargo, siempre puede crearlos a mano directamente en la base de datos, la mayoría de las bases de datos los recogerán automáticamente durante la planificación de consultas.

Con JPA 2.1 deberías poder hacerlo.

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

Actualización : si alguna vez necesita crear e indexar con dos o más columnas, puede usar comas. Por ejemplo:

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

¡JPA 2.1 (finalmente) agrega soporte para índices y claves externas! Mira este blog para más detalles. JPA 2.1 es una parte de Java EE 7, que está fuera.

Si le gusta vivir al límite, puede obtener la última instantánea de eclipselink de su repository de maven (groupId: org.eclipse.persistence, artifactId: eclipselink, version: 2.5.0-SNAPSHOT). Solo para las anotaciones JPA (que deberían funcionar con cualquier proveedor una vez que sean compatibles con 2.1) use artifactID: javax.persistence, version: 2.1.0-SNAPSHOT.

Lo estoy usando para un proyecto que no estará terminado hasta después de su lanzamiento, y no he notado ningún problema horrible (aunque no estoy haciendo nada demasiado complejo con él).

ACTUALIZACIÓN (26 de septiembre de 2013): hoy en día, las versiones candidatas de lanzamiento y lanzamiento de eclipselink están disponibles en el repository central (principal), por lo que ya no es necesario agregar el repository eclipselink en los proyectos de Maven. La última versión de lanzamiento es 2.5.0 pero 2.5.1-RC3 también está presente. Cambiaría a 2.5.1 lo antes posible debido a problemas con la versión 2.5.0 (las cosas modelgen no funcionan).

Una colección única de anotaciones de índice seleccionadas a mano

= Especificaciones =

  • JPA 2.1+: javax.persistence.Index (o ver JSR-000338 PDF, p.42, elemento 11.1.23)
    La anotación JPA @Index solo se puede usar como parte de otra anotación como @Table , @SecondaryTable , etc .:

     @Table(indexes = { @Index(...) }) 
  • JDO 2.1+: javax.jdo.annotations.Index

= ORM Frameworks =

  • ♥ Hibernate ORM : org.hibernate.annotations.Index ;
  • OpenJPA : org.apache.openjpa.persistence.jdbc.Index y org.apache.openjpa.persistence.jdbc.ElementIndex (consulte la Guía de referencia );
  • EclipseLink : org.eclipse.persistence.annotations.Index ;
  • DataNucleus : org.datanucleus.api.jpa.annotations.Index ;
  • Carbonado (GitHub) : com.amazon.carbonado.Index ;
  • EBean : com.avaje.ebean.annotation.Index o io.ebean.annotation.Index?
  • Ujorm : Anotación org.ujorm.orm.annot.Column , index y propiedades uniqueIndex ;
  • requery ( GitHub . Java, Kotlin, Android): Annotation io.requery.Index ;
  • Expuesto ( Kotlin SQL Library): org.jetbrains.exposed.sql.Index , org.jetbrains.exposed.sql.Table # index () . Ejemplo:

     object Persons : IdTable() { val code = varchar("code", 50).index() } 

= ORM para Android =

  • ♥ ActiveAndroid : Annotation com.activeandroid.annotation.Column tiene com.activeandroid.annotation.Column index , indexGroups , unique y uniqueGroups ;
    ACTUALIZACIÓN [2018]: ActiveAndroid fue un buen ORM hace 4 años, pero desafortunadamente, el autor de la biblioteca dejó de mantenerlo, por lo que alguien bifurcó, corrigió errores y lo marcó como ReActiveAndroid . Úselo si está comenzando un nuevo proyecto o consulte la Guía de migración si desea reemplazar ActiveAndroid en un proyecto heredado.
  • ReActiveAndroid : Annotation com.reactiveandroid.annotation.Column tiene com.reactiveandroid.annotation.Column index , indexGroups , unique y uniqueGroups ;
  • ORMLite : Annotation com.j256.ormlite.field.DatabaseField tiene una propiedad de index ;
  • greenDAO : org.greenrobot.greendao.annotation.Index ;
  • ORMAN (GitHub) : org.orman.mapper.annotation.Index ;
  • ★ DBFlow (GitHub) : com.raizlabs.android.dbflow.sql.index.Index ( ejemplo de uso);
  • otro .

= Otro (difícil de categorizar) =

  • Realm – Alternative DB para iOS / Android: Annotation io.realm.annotations.Index ;
  • Empire-db : una capa de abstracción de bases de datos relacionales ligera pero poderosa basada en JDBC. No tiene definición de esquema a través de anotaciones;
  • Kotlin NoSQL (GitHub) : una DSL reactiva y segura para tipos para trabajar con bases de datos NoSQL (PoC): ???

Solo opta por uno de ellos.

Realmente me gustaría poder especificar índices de bases de datos de manera estandarizada pero, por desgracia, esto no forma parte de la especificación JPA (tal vez porque la especificación JPA no requiere soporte de generación DDL, que es una especie de bloque de carreteras para tal característica).

Por lo tanto, tendrá que confiar en una extensión específica del proveedor para eso. Hibernate, OpenJPA y EclipseLink claramente ofrecen tal extensión. No puedo confirmar DataNucleus, pero como la definición de los índices forma parte de JDO, creo que sí.

Realmente espero que el soporte de índice se estandarice en las próximas versiones de la especificación y por lo tanto no esté de acuerdo con otras respuestas, no veo ninguna buena razón para no incluir tal cosa en JPA (especialmente porque la base de datos no siempre está bajo su control) para un soporte óptimo de generación de DDL.

Por cierto, sugiero descargar la especificación JPA 2.0.

En JPA 2.1, debe hacer lo siguiente

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

En el ejemplo anterior, la tabla TEST_PERSON tendrá 3 índices:

  • índice único en la identificación de la clave principal

  • índice en AGE

  • índice compuesto en FNAME, SNAME

Nota 1: Obtiene el índice compuesto al tener dos anotaciones @Index con el mismo nombre

Nota 2: especifica el nombre de la columna en columnList not the fieldName

EclipseLink proporcionó una anotación (por ejemplo, @Index ) para definir un índice en columnas. Hay un ejemplo de su uso. Parte del ejemplo está incluido …

Los campos firstName y lastName están indexados, juntos 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; ... } 

OpenJPA le permite especificar una anotación no estándar para definir el índice en la propiedad.

Los detalles estan aqui

Para resumir las otras respuestas:

  • Hibernate: org.hibernate.annotations.Index
  • OpenJPA: org.apache.openjpa.persistence.jdbc.Index
  • EclipseLink: org.eclipse.persistence.annotations.Index

Yo solo iría por uno de ellos. Viene con JPA 2.1 de todos modos y no debería ser demasiado difícil de cambiar en el caso de que realmente desee cambiar su proveedor de JPA.

No es posible hacer eso usando la anotación JPA. Y esto tiene sentido: donde una UniqueConstraint define claramente las reglas de un negocio, un índice es solo una forma de acelerar la búsqueda. Entonces esto realmente debería ser hecho por un DBA.

Esta solución es para EclipseLink 2.5 y funciona (probado):

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

Esto supone un orden ascendente.

Intereting Posts