不成功:在Hibernate / JPA / HSQLDB独立版本中使用alter table XXX drop constraint YYY

我正在尝试使用内存中的HSQL DB运行一些Hibernate / JPA示例。 我得到的错误信息如下:

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 

相应的类是:

 @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 } 

可embedded的是:

 @Embeddable public class AnEmbeddable implements Serializable { private String s; public AnEmbeddable() { } public String getS() { return s; } public void setS(String s) { this.s = s; } } 

我的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> 

我在Hibernate 4.1.5.FinalHSQLDB 2.2.8

有谁知道是什么原因导致这个问题,以及如何解决?

你可以忽略这些错误。 create-drop和in-memory数据库的组合为每个试图删除的数据库对象生成这些数据库对象。 原因是没有任何数据库对象要删除 – 对空数据库执行DROP语句。

也正常的永久性数据库这样的错误来了,因为Hibernate没有find执行DROP语句之前添加对象存在于数据库或新的。

这个解决scheme为我工作,而不是给出的另一个解决scheme。 显然里程不一。

这是我的确切错误:

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

这是我的解决scheme,覆盖H2方言:

 package com.totaalsoftware.incidentmanager; import org.hibernate.dialect.H2Dialect; /** * Workaround. * * @see https://hibernate.onjira.com/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; } } 

上面提供的解决scheme@Sander也适用于MYSQL。 只需像下面那样扩展MySQL5InnoDBDialect:

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

然后在您的数据源文件中更改以下行:

 dialect = org.hibernate.dialect.MySQL5InnoDBDialect 

 dialect = my.package.name.ImprovedMySQLDialect 

只要设置dbCreate="update" ,错误立即消失。

请参阅: https : //stackoverflow.com/a/31257468/715608

在每次testing开始时,恼人的错误消息变成了更令人讨厌的堆栈跟踪,使用带有HSQLDB和hbm2ddl.auto = create-drop的内存数据库。

对HSQLDB错误报告的响应build议使用DROP TABLE … CASCADE,而不是DROP CONSTRAINT IF EXISTS。 不幸的是,drop table的HSQLDB语法是DROP TABLE <table> [IF EXISTS] [RESTRICT | CASCADE]; DROP TABLE <table> [IF EXISTS] [RESTRICT | CASCADE]; Hibernate Dialect没有提供方便的机制来指定最后的IF EXISTS子句之后的CASCADE。 我为这个限制写了一个bug 。

不过,我可以通过创build一个自定义方言来解决这个问题,如下所示:

 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; }; } 
Interesting Posts