18

Tengo funciones de hibernación controladas por anotaciones en mi proyecto.Creación de índices en DB con hibernación @Index Annotation

Ahora quiero crear un índice sobre una columna. Mi definición de la columna actual es

@NotNull 
@Column(name = "hash") 
private String hash; 

y añadir @Index anotación aquí.

@NotNull 
@Column(name = "hash") 
@Index(name="hashIndex") 
private String hash; 

y luego DROP TABLE y reinicia el servidor Tomcat. Después de crear una instancia del servidor, se crea la tabla, pero no puedo ver el nuevo índice en la siguiente consulta.

SHOW INDEX FROM tableName 

Se espera que construya la tabla con el nuevo índice. Estoy usando InnoDB con MySQL.

Respuesta

16

Curiosamente, en mi configuración de Hibernate estaba usando hibernate.hbm2ddl.auto=update.

Éste modifica una base de datos existente. Estaba DROPlando manualmente la tabla tableName y reiniciando Tomcat y la tabla había sido construida pero el índice no se estaba creando.

Sin embargo, hice hibernate.hbm2ddl.auto=create que recrea la base de datos en cada instanciación de la aplicación web, se cayó toda mi base de datos y se reconstruyó de nuevo y -hell sí-mi nuevo índice ha sido creado!

+0

Sí, me di cuenta de este comportamiento también. +1 por todos lados. –

+0

¿Pero es seguro ese ajuste 'auto.create' para la producción? http://stackoverflow.com/a/221422/409976 de no ser así, ¿cómo manejas los índices con hibernación? –

+1

https://hibernate.atlassian.net/browse/HHH-1012 corregido, ahora también funciona con 'update'. – gavenkoa

9

La creación de índices en la actualización del esquema se ha desactivado intencionadamente en Hibernate porque parece ser incoherente con la denominación utilizada en la exportación del esquema.

Este es el código comentado que puede encontrar en la clase org.hibernate.cfg.Configuration.

//broken, 'cos we don't generate these with names in SchemaExport 
subIter = table.getIndexIterator(); 
while (subIter.hasNext()) { 
    Index index = (Index) subIter.next(); 
    if (!index.isForeignKey() || !dialect.hasImplicitIndexForForeignKey()) { 
     if (tableInfo==null || tableInfo.getIndexMetadata(index.getFilterName()) == null) { 
      script.add(index.sqlCreateString(dialect, mapping)); 
     } 
    } 
} 
//broken, 'cos we don't generate these with names in SchemaExport 
subIter = table.getUniqueKeyIterator(); 
while (subIter.hasNext()) { 
    UniqueKey uk = (UniqueKey) subIter.next(); 
    if (tableInfo==null || tableInfo.getIndexMetadata(uk.getFilterName()) == null) { 
     script.add(uk.sqlCreateString(dialect, mapping)); 
    } 
} 

lo general, me quite ese comentario, recompilar Hibernate.jar y tienen índices creados en la actualización del esquema sin ningún problema, al menos con la base de datos Oracle.

En las versiones recientes de Hibernate, el comentario en la primera parte (índices de tabla) también se ha eliminado en la versión oficial, mientras que aún se comenta el segundo (índices que implementan claves únicas). Consulte la discusión en http://opensource.atlassian.com/projects/hibernate/browse/HHH-1012

+2

solo para respaldar esta respuesta: la actualización de la base de datos para crear índices me funciona usando hibernate 4.1.3 y mysq. Los índices se crean automáticamente para mí sin descartar y volver a crear tablas si agrego una anotación @Index a una entidad. – jportway

2

En Hibernate 3.5.6 usando <property name="hibernate.hbm2ddl.auto">update</property> se crean los índices. Entonces, una respuesta adecuada sería actualizar. Pero dejo esta respuesta para aquellos que como yo hemos encontrado esta pregunta.

+0

Sí. https://hibernate.atlassian.net/browse/HHH-1012 arreglado en 3.2.x, 3.3.x, 3.5.0-Beta-2 – gavenkoa

4

Mejor diseño de base de datos significa que el esquema es propiedad de un usuario diferente de los datos en sí. Por lo tanto, establezco hibernate.hbm2ddl.auto=none para que no haya fallas en el inicio de Hibernate. Yo uso una SchemaPrinter en su lugar. El resultado del cual se puede ejecutar a través de mi herramienta SQL favorita para volver a crear el esquema cuando sea necesario.

import java.io.IOException; 

import org.hibernate.cfg.AnnotationConfiguration; 
import org.hibernate.cfg.Configuration; 
import org.hibernate.cfg.Environment; 
import org.hibernate.tool.hbm2ddl.SchemaExport; 

public class SchemaPrinter { 

    public static void main(String[] args) throws IOException { 

     Configuration cfg = new AnnotationConfiguration() 
      .addAnnotatedClass(MyClass1.class) 
      .addAnnotatedClass(MyClass2.class) 
      .setProperty(Environment.USER, "user") 
      .setProperty(Environment.PASS, "password") 
      .setProperty(Environment.URL, "jdbc:sybase:jndi:file://sql.ini?mydb") 
      .setProperty(Environment.DIALECT, "org.hibernate.dialect.SybaseASE15Dialect") 
      .setProperty(Environment.DRIVER, "com.sybase.jdbc4.jdbc.SybDriver") 
      .setProperty(Environment.HBM2DDL_AUTO, "none") 
     SchemaExport exp = new SchemaExport(cfg); 
     exp.setOutputFile("schema.ddl"); 
     exp.create(true, false); 
    } 

}