web-dev-qa-db-fra.com

Échec: modifier la contrainte de suppression de la table XXX YYY dans Hibernate / JPA / HSQLDB autonome

J'essaie d'exécuter des exemples Hibernate/JPA en utilisant une base de données HSQL en mémoire. Le message d'erreur que je reçois est le suivant:

13:54:21,427 ERROR SchemaExport:425 - HHH000389: Unsuccessful: alter table ReferringItem_map drop constraint FK5D4A98E0361647B8
13:54:21,427 ERROR SchemaExport:426 - user lacks privilege or object not found: PUBLIC.REFERRINGITEM_MAP
13:54:21,427 ERROR SchemaExport:425 - HHH000389: Unsuccessful: alter table ReferringItem_myCollection drop constraint FK75BA3266361647B8
13:54:21,427 ERROR SchemaExport:426 - user lacks privilege or object not found: PUBLIC.REFERRINGITEM_MYCOLLECTION
13:54:21,428 ERROR SchemaExport:425 - HHH000389: Unsuccessful: alter table ReferringItem_myList drop constraint FK6D37AA66361647B8
13:54:21,428 ERROR SchemaExport:426 - user lacks privilege or object not found: PUBLIC.REFERRINGITEM_MYLIST
13:54:21,428 ERROR SchemaExport:425 - HHH000389: Unsuccessful: alter table ReferringItem_mySet drop constraint FK3512699A361647B8
13:54:21,429 ERROR SchemaExport:426 - user lacks privilege or object not found: PUBLIC.REFERRINGITEM_MYSET

La classe correspondante est:

@Entity
public class ReferringItem implements Serializable {

    @Id
    private long id;

    @ElementCollection
    private Collection<AnEmbeddable> myCollection
        = new ArrayList<AnEmbeddable>();

    @ElementCollection(fetch=FetchType.EAGER)
    private Set<Long> mySet = new HashSet<Long>();

    @ElementCollection(targetClass=String.class)
    private List myList = new ArrayList();

    @ElementCollection
    private Map<String,AnEmbeddable> map
        = new HashMap<String,AnEmbeddable>();

    public ReferringItem() { }

    // Setters & Getters

}

L'embarqué est:

@Embeddable
public class AnEmbeddable implements Serializable {

    private String s;

    public AnEmbeddable() { }

    public String getS() {
        return s;
    }

    public void setS(String s) {
        this.s = s;
    }

}

Ma persistence.xml:

<persistence xmlns="http://Java.Sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://Java.Sun.com/xml/ns/persistence http://Java.Sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">

    <persistence-unit name="JPA" transaction-type="RESOURCE_LOCAL">

        <provider>org.hibernate.ejb.HibernatePersistence</provider>

        <class>com.jverstry.jpa.AuthorizedTypes.AuthorizedTypes</class>
        <class>com.jverstry.jpa.AuthorizedTypes.OtherEntity</class>
        <class>com.jverstry.jpa.AuthorizedTypes.SomeEmbeddable</class>

        <properties>
            <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:testdb"/>
            <property name="javax.persistence.jdbc.user" value="sa"/>
            <property name="javax.persistence.jdbc.password" value=""/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
        </properties>

    </persistence-unit>

</persistence>

Je suis sur Hibernate 4.1.5.Final et HSQLDB 2.2.8.

Quelqu'un sait-il ce qui cause ce problème et comment le résoudre?

40
Jérôme Verstrynge

Vous pouvez ignorer ces erreurs. Combinaison de create-drop et la base de données en mémoire les produit pour chaque objet de base de données qu'elle essaie de supprimer. La raison étant qu'il n'y a aucun objet de base de données à supprimer - les instructions DROP sont exécutées sur une base de données vide.

De plus, avec une base de données permanente normale, de telles erreurs se produisent, car Hibernate ne comprend pas avant d'exécuter des instructions DROP que l'objet ajouté existe dans la base de données ou est-il nouveau.

55
Mikko Maunu

Cette solution a fonctionné pour moi, contrairement à l'autre solution qui a été donnée. Apparemment, le kilométrage varie.

Ce fut mon erreur exacte:

HHH000389: Unsuccessful: alter table ... drop constraint FK_g1uebn6mqk9qiaw45vnacmyo2 if exists
Table "..." not found; SQL statement: ...

Voici ma solution, en remplaçant le dialecte H2:

package com.totaalsoftware.incidentmanager;

import org.hibernate.dialect.H2Dialect;

/**
 * Workaround.
 * 
 * @see https://hibernate.atlassian.net/browse/hhh-7002
 * 
 */
public class ImprovedH2Dialect extends H2Dialect {
    @Override
    public String getDropSequenceString(String sequenceName) {
        // Adding the "if exists" clause to avoid warnings
        return "drop sequence if exists " + sequenceName;
    }

    @Override
    public boolean dropConstraints() {
        // We don't need to drop constraints before dropping tables, that just
        // leads to error messages about missing tables when we don't have a
        // schema in the database
        return false;
    }
}
28
Sander Verhagen

La solution @Sander fournie ci-dessus fonctionne également pour MYSQL. Étendez simplement MySQL5InnoDBDialect à la place comme ci-dessous:

import org.hibernate.dialect.MySQL5InnoDBDialect;

public class ImprovedMySQLDialect extends MySQL5InnoDBDialect {
    @Override
    public String getDropSequenceString(String sequenceName) {
        // Adding the "if exists" clause to avoid warnings
        return "drop sequence if exists " + sequenceName;
    }

    @Override
    public boolean dropConstraints() {
        // We don't need to drop constraints before dropping tables, that just leads to error
        // messages about missing tables when we don't have a schema in the database
        return false;
    }
}

Ensuite, dans votre fichier de source de données, modifiez la ligne suivante:

dialect = org.hibernate.dialect.MySQL5InnoDBDialect

à

dialect = my.package.name.ImprovedMySQLDialect
12
Emmanuel John

Réglez simplement dbCreate="update", et les erreurs disparaissent immédiatement.

Voir: https://stackoverflow.com/a/31257468/715608

12
10GritSandpaper

Les messages d'erreur gênants sont devenus des traces de pile plus désagréables au début de chaque test en utilisant une base de données en mémoire avec HSQLDB et hbm2ddl.auto = create-drop.

La réponse à un rapport de bogue HSQLDB a suggéré l'utilisation de DROP TABLE ... CASCADE plutôt que DROP CONSTRAINT IF EXISTS. Malheureusement, la syntaxe HSQLDB pour la table de dépôt est DROP TABLE <table> [IF EXISTS] [RESTRICT | CASCADE]; Hibernate Dialect ne fournit pas de mécanisme simple permettant à un dialecte de spécifier CASCADE après la dernière clause IF EXISTS. J'ai écrit n bug pour cette limitation.

Cependant, j'ai pu surmonter le problème en créant un dialecte personnalisé comme suit:

public class HsqlDialectReplacement extends HSQLDialect {

  @Override
  public String getDropTableString( String tableName ) {
    // Append CASCADE to formatted DROP TABLE string
    final String superDrop = super.getDropTableString( tableName );
    return superDrop + " cascade";
  }

  @Override
  public boolean dropConstraints() {
      // Do not explicitly drop constraints, use DROP TABLE ... CASCADE
      return false;
  }

  @Override
  public Exporter<Table> getTableExporter() {
    // Must override TableExporter because it also formulates DROP TABLE strings
    synchronized( this ) {
      if( null == overrideExporter ) {
        overrideExporter = new HsqlExporter( super.getTableExporter() );
      }
    }

    return overrideExporter;
  }

  private Exporter<Table> overrideExporter = null;

  private static class HsqlExporter implements Exporter<Table> {
    HsqlExporter( Exporter<Table> impl ) {
      this.impl = impl;
    }

    @Override
    public String[] getSqlCreateStrings( Table exportable, Metadata metadata ) {
      return impl.getSqlCreateStrings( exportable, metadata );
    }

    @Override
    public String[] getSqlDropStrings( Table exportable, Metadata metadata ) {
      final String[] implDrop = impl.getSqlDropStrings( exportable, metadata );
      final String[] dropStrings = new String[implDrop.length];
      for( int i=0; i<implDrop.length; ++i ) {
        dropStrings[i] = implDrop[i] + " cascade";
      }
      return dropStrings;
    }

    private final Exporter<Table> impl;
  };
}
2
wbdarby

Nous avons rencontré le même problème en essayant de créer une fenêtre de connexion simple dans Spring. Il y avait deux tables user et role toutes les deux avec la clé primaire id type de BIGINT. Celles-ci nous avons cartographié (Many-to-Many) dans une autre table user_roles avec deux colonnes user_id et role_id comme clés étrangères.

Le problème était le role_id colonne dans user_roles table, elle était de type int et non compatible pour la clé étrangère à role. Lorsque le type a été modifié en BIGINT les erreurs ont été corrigées.

0
Arun Sudhakaran