[英]Unsuccessful: alter table XXX drop constraint YYY in Hibernate/JPA/HSQLDB standalone
我正在嘗試使用內存中的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
}
可嵌入的是:
@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.Final
和HSQLDB 2.2.8
。
有誰知道導致此問題的原因以及如何解決?
您可以忽略這些錯誤。 create-drop
和empty(內存中的情況總是如此)的組合會為它嘗試刪除的每個數據庫對象生成這些。 原因是沒有要刪除的任何數據庫對象-針對空數據庫執行DROP語句。
同樣,對於普通的永久數據庫,也會出現這樣的錯誤,因為Hibernate在執行DROP語句之前並不會確定數據庫中是否存在添加的對象或者它是新對象。
與給定的其他解決方案相反,該解決方案對我有用。 顯然,里程數有所不同。
這是我的確切錯誤:
HHH000389: Unsuccessful: alter table ... drop constraint FK_g1uebn6mqk9qiaw45vnacmyo2 if exists
Table "..." not found; SQL statement: ...
這是我的解決方案,覆蓋了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;
}
}
上面提供的解決方案@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"
,錯誤就會立即消失。
使用帶有HSQLDB和hbm2ddl.auto = create-drop的內存數據庫,在每次測試開始時,令人討厭的錯誤消息都變得更加令人討厭。
對HSQLDB錯誤報告的響應建議使用DROP TABLE ... CASCADE而不是DROP CONSTRAINT IF EXISTS。 不幸的是,刪除表的HSQLDB語法是DROP TABLE <table> [IF EXISTS] [RESTRICT | CASCADE];
DROP TABLE <table> [IF EXISTS] [RESTRICT | CASCADE];
Hibernate方言沒有提供一種簡單的機制來讓方言在最終的IF EXISTS子句之后指定CASCADE。 我為此限制編寫了一個錯誤 。
但是,我可以通過如下創建自定義方言來解決此問題:
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;
};
}
在Spring
嘗試創建一個簡單的登錄窗口時,我們遇到了同樣的問題。 有兩個表user
和role
它們的主鍵id
類型均為BIGINT
。 我們將它們映射( Many-to-Many
)到另一個表user_roles
其中有兩列user_id
和role_id
作為外鍵。
問題出在user_roles
表中的role_id
列,它是int
類型的,並且與role
的外鍵不兼容。 將類型修改為BIGINT
錯誤已得到糾正。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.