18

J'ai des capacités d'hibernation pilotées par annotations sur mon projet.Création d'index sur la base de données avec l'annotation Hibernate @Index

Maintenant, je veux créer un index sur une colonne. Ma définition actuelle de la colonne est

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

et j'ajouter @Index annotation ici.

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

puis de déposer TABLE et redémarrer le serveur Tomcat. Une fois le serveur instancié, la table est créée mais je ne vois pas d'index sur la requête suivante.

SHOW INDEX FROM tableName 

Il est prévu de construire une table avec un nouvel index. J'utilise InnoDB avec MySQL.

Répondre

16

Fait intéressant, dans ma configuration Hibernate j'utilisais hibernate.hbm2ddl.auto=update.

Celui-ci modifie une base de données existante. Je supprimais manuellement la table tableName et redémarrer Tomcat et la table avait été construite mais l'index n'était pas créé.

Cependant, j'ai fait hibernate.hbm2ddl.auto=create qui recrée la base de données à chaque instanciation de webapp, il a laissé tomber toute ma base de données et reconstruit en arrière et -hell yeah- mon nouvel index a été créé!

+0

Oui, j'ai remarqué ce comportement aussi. +1 tout autour. –

+0

Mais ce paramètre 'auto.create' est-il sûr pour la production? http://stackoverflow.com/a/221422/409976 Sinon, comment gérez-vous les index avec Hibernate? –

+1

https://hibernate.atlassian.net/browse/HHH-1012 fixed, fonctionne maintenant avec 'update' aussi. – gavenkoa

9

La création d'index sur la mise à jour de schéma a été intentionnellement désactivée dans Hibernate car elle semblait incompatible avec la dénomination utilisée dans l'exportation de schéma.

Ceci est le code commenté que vous pouvez trouver dans la classe 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)); 
    } 
} 

Habituellement je supprimer ce commentaire, recompiler Hibernate.jar et ont des index créés sur la mise à jour du schéma sans aucun problème, au moins avec Oracle DB.

Dans les versions récentes d'Hibernate, le commentaire sur la première partie (index de table) a été supprimé dans la version officielle, alors qu'il est toujours commenté le second (index qui implémentent des clés uniques). Voir la discussion au http://opensource.atlassian.com/projects/hibernate/browse/HHH-1012

+2

juste pour sauvegarder cette réponse - mettre à jour la base de données pour créer des index fonctionne pour moi en utilisant hibernate 4.1.3 et mysq. Les index sont créés pour moi automatiquement sans supprimer et recréer des tables si j'ajoute une annotation @Index à une entité. – jportway

2

Dans Hibernate 3.5.6 en utilisant <property name="hibernate.hbm2ddl.auto">update</property> les index sont créés. Donc, une bonne réponse maintenant serait d'améliorer. Mais je laisse cette réponse à ceux qui, comme moi, ont rencontré cette question.

+0

Oui. https://hibernate.atlassian.net/browse/HHH-1012 corrigé dans 3.2.x, 3.3.x, 3.5.0-Beta-2 – gavenkoa

4

Une meilleure conception de base de données signifie que le schéma appartient à un utilisateur différent des données elles-mêmes. Par conséquent, j'ai mis hibernate.hbm2ddl.auto=none donc il n'y a pas d'échec lors du démarrage d'Hibernate. J'utilise un SchemaPrinter à la place. La sortie de ce qui peut être exécuté via mon outil SQL favori pour recréer le schéma lorsque cela est nécessaire.

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

}