java - index - Especificación de un índice(clave no única) mediante JPA
jpa index (11)
¿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 hibernar y datanucleus.
ACTUALIZAR:
A partir de JPA 2.1, puedes hacer esto. Ver: la anotación @Index no está permitida para esta ubicación
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(...) })
= ORM Frameworks =
- ♥ Hibernate ORM :
org.hibernate.annotations.Index
; - OpenJPA :
org.apache.openjpa.persistence.jdbc.Index
yorg.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 propiedadesuniqueIndex
; - requery ( GitHub . Java, Kotlin, Android): Annotation
io.requery.Index
; Exposed ( 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
tienecom.activeandroid.annotation.Column
index
,indexGroups
,unique
yuniqueGroups
;
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 . ReActiveAndroid 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
tienecom.reactiveandroid.annotation.Column
index
,indexGroups
,unique
yuniqueGroups
; - ORMLite : Annotation
com.j256.ormlite.field.DatabaseField
tiene una propiedad deindex
; - greenDAO :
org.greenrobot.greendao.annotation.Index
; - ORMAN (GitHub) :
org.orman.mapper.annotation.Index
; - ★ DBFlow (GitHub) :
com.raizlabs.android.dbflow.sql.index.Index
( example de uso); - other .
= 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.
¡JPA 2.1 (finalmente) agrega soporte para índices y claves externas! Mira blogs.oracle.com/arungupta/entry/jpa_2_1_schema_generation 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 repositorio 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 repositorio central (principal), por lo que ya no es necesario agregar el repositorio 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).
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{
EclipseLink proporcionó una anotación (por ejemplo, @Index ) para definir un índice en columnas. Hay un example 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;
...
}
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
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.
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.
OpenJPA le permite especificar una anotación no estándar para definir el índice en la propiedad.
Los detalles estan here
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.
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.
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.