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?
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.
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;
}
}
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
Réglez simplement dbCreate="update"
, et les erreurs disparaissent immédiatement.
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;
};
}
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.