2012-09-11 59 views
1

我正在嘗試使用H2數據庫進行單元測試。我的實際數據庫是MYSQL,所以我用H2的MYSQL方言。一旦hbm文件被讀取/加載,問題就會出現。由於H2或Hibernate試圖改變表格,所以外鍵/關聯會失去作用,或者看起來如此。Hibernate/H2外鍵拋出org.h2.jdbc.JdbcSQLException

DB腳本:

DROP SCHEMA IF EXISTS `amr` ; 
CREATE SCHEMA IF NOT EXISTS `amr`; 

-- ----------------------------------------------------- 
-- Table `amr`.`classA` 
-- ----------------------------------------------------- 
DROP TABLE IF EXISTS `amr`.`classA` ;CREATE TABLE IF NOT EXISTS `amr`.`classA` (
    `classA_id` INT(11) NOT NULL , 
    `name` VARCHAR(56) NOT NULL , 
    PRIMARY KEY (`classA_id`)); 

-- ----------------------------------------------------- 
-- Table `amr`.`classB` 
-- ----------------------------------------------------- 
DROP TABLE IF EXISTS `amr`.`classB` ;CREATE TABLE IF NOT EXISTS `amr`.`classB` (
    `classB_id` INT(11) NOT NULL , 
    `name` VARCHAR(45) NOT NULL , 
    `classA_id` INT(11) NOT NULL , 
    PRIMARY KEY (`classB_id`) , 
    INDEX `fk_classB_service_provider_classA1` (`classA_id` ASC) , 
    CONSTRAINT `fk_classB_service_provider_classA1` 
    FOREIGN KEY (`classA_id`) 
    REFERENCES `amr`.`classA` (`classA_id`) 
    ON DELETE NO ACTION 
    ON UPDATE NO ACTION); 

例外,我得到:

09-11 08:46:33 jdbc[2]: exception 
org.h2.jdbc.JdbcSQLException: Column "FOREIGN" not found; SQL statement: 
alter table amr.classB drop foreign key FKAF0F85CABD96B12B [42122-168] 
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:329) 
    at org.h2.message.DbException.get(DbException.java:169) 
    at org.h2.message.DbException.get(DbException.java:146) 
    at org.h2.table.Table.getColumn(Table.java:605) 
    at org.h2.command.Parser.parseAlterTable(Parser.java:4874) 
    at org.h2.command.Parser.parseAlter(Parser.java:4315) 
    at org.h2.command.Parser.parsePrepared(Parser.java:306) 
    at org.h2.command.Parser.parse(Parser.java:279) 
    at org.h2.command.Parser.parse(Parser.java:251) 
    at org.h2.command.Parser.prepareCommand(Parser.java:217) 
    at org.h2.engine.Session.prepareLocal(Session.java:415) 
    at org.h2.engine.Session.prepareCommand(Session.java:364) 
    at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1109) 
    at org.h2.jdbc.JdbcStatement.executeUpdateInternal(JdbcStatement.java:121) 
    at org.h2.jdbc.JdbcStatement.executeUpdate(JdbcStatement.java:110) 
    at org.hibernate.tool.hbm2ddl.SchemaExport.execute(SchemaExport.java:421) 
    at org.hibernate.tool.hbm2ddl.SchemaExport.drop(SchemaExport.java:396) 
    at org.hibernate.tool.hbm2ddl.SchemaExport.execute(SchemaExport.java:269) 
    at org.hibernate.tool.hbm2ddl.SchemaExport.create(SchemaExport.java:219) 
    at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:370) 
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1842) 
    at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory(LocalSessionFactoryBean.java:860) 
    at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:779) 
    at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:188) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:567) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464) 
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:103) 
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1) 
    at org.springframework.test.context.support.DelegatingSmartContextLoader.loadContext(DelegatingSmartContextLoader.java:228) 
    at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124) 
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75) 
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
09-11 08:46:33 jdbc[2]: exception 
org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "ALTER TABLE AMR.CLASSB ADD INDEX FKAF0F85CABD96B12B (CLASSA_ID),[*] ADD CONSTRAINT FKAF0F85CABD96B12B FOREIGN KEY (CLASSA_ID) REFERENCES AMR.CLASSA (ID) "; SQL statement: 
alter table amr.classB add index FKAF0F85CABD96B12B (classA_id), add constraint FKAF0F85CABD96B12B foreign key (classA_id) references amr.classA (id) [42000-168] 
09-11 08:46:34 jdbc[2]: exception 
org.h2.jdbc.JdbcSQLException: Column "FOREIGN" not found; SQL statement: 
alter table amr.classB drop foreign key FKAF0F85CABD96B12B [42122-168] 
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:329) 
    at org.h2.message.DbException.get(DbException.java:169) 
    at org.h2.message.DbException.get(DbException.java:146) 
    at org.h2.table.Table.getColumn(Table.java:605) 
    at org.h2.command.Parser.parseAlterTable(Parser.java:4874) 
    at org.h2.command.Parser.parseAlter(Parser.java:4315) 
    at org.h2.command.Parser.parsePrepared(Parser.java:306) 
    at org.h2.command.Parser.parse(Parser.java:279) 
    at org.h2.command.Parser.parse(Parser.java:251) 
    at org.h2.command.Parser.prepareCommand(Parser.java:217) 
    at org.h2.engine.Session.prepareLocal(Session.java:415) 
    at org.h2.engine.Session.prepareCommand(Session.java:364) 
    at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1109) 
    at org.h2.jdbc.JdbcStatement.executeUpdateInternal(JdbcStatement.java:121) 
    at org.h2.jdbc.JdbcStatement.executeUpdate(JdbcStatement.java:110) 
    at org.hibernate.tool.hbm2ddl.SchemaExport.execute(SchemaExport.java:421) 
    at org.hibernate.tool.hbm2ddl.SchemaExport.drop(SchemaExport.java:396) 
    at org.hibernate.tool.hbm2ddl.SchemaExport.execute(SchemaExport.java:269) 
    at org.hibernate.tool.hbm2ddl.SchemaExport.drop(SchemaExport.java:229) 
    at org.hibernate.impl.SessionFactoryImpl.close(SessionFactoryImpl.java:959) 
    at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.destroy(AbstractSessionFactoryBean.java:228) 
    at org.springframework.orm.hibernate3.LocalSessionFactoryBean.destroy(LocalSessionFactoryBean.java:899) 
    at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:211) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:498) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:474) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:442) 
    at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1066) 
    at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1040) 
    at org.springframework.context.support.AbstractApplicationContext$1.run(AbstractApplicationContext.java:958) 

HBM映射:

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping default-access="field"> 
    <class name="ClassA" table="classA"> 
     <id name="id" type="long"> 
      <column name="id"/> 
     </id> 
     <property name="name" type="string"> 
      <column name="name" length="56" not-null="true"/> 
     </property> 
     <set name="classBs" table="classB" inverse="true" lazy="true" fetch="select"> 
      <key> 
       <column name="classA_id" not-null="true"/> 
      </key> 
      <one-to-many class="ClassB"/> 
     </set> 
    </class> 
</hibernate-mapping> 

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping default-access="field"> 
    <class name="ClassB" table="classB"> 
     <id name="id" type="long"> 
      <column name="id"/> 
     </id> 
     <property name="name" type="string"> 
      <column name="name" length="56" not-null="true"/> 
     </property> 
     <many-to-one name="classA" class="ClassA" fetch="select"> 
      <column name="classA_id" not-null="true"/> 
     </many-to-one> 
    </class> 
</hibernate-mapping> 

H2網址:

jdbc:h2:~/db/amr_test;MODE=MYSQL;INIT=create schema if not exists test_db\\;runscript from 'classpath:amr_test_ddl.sql';DB_CLOSE_ON_EXIT=FALSE 

-------------------編輯/找到問題--------------- -------------------

幾乎從頭開始重新評估一切,發現我不正確地將下面的屬性添加到我的上下文文件中:

創建刪除

在其中一個論壇中,指導我的H2上下文配置指向使用它,因爲它「在會話關閉後刪除模式」。

所以我對這個屬性的無知導致了一個教訓。

@Thomas Mueller - 非常感謝您在這件事上的時間和協助。

+0

如果您改用H2方言(並刪除MODE = MYSQL),它會起作用嗎?我想你無論如何都需要有兩個Hibernate配置(一個用於測試,一個用於生產)。 Hibernate應該能夠抽象數據庫特定的功能,因此如果在生產中使用不同的數據庫,則不需要太在意。 –

+0

當我更改爲h2方言時,它對我的​​ddl語法不滿意: org.h2.jdbc.JdbcSQLException:未知數據類型:「FK_CLASSB_SERVICE_PROVIDER_CLASSA1」; SQL語句: CREATE TABLE IF NOT EXISTS'amr'.'classB'( 'classB_id' INT(11)NOT NULL, 'name' VARCHAR(45)NOT NULL, 'classA_id' INT(11)NOT NULL, PRIMARY KEY('classB_id') INDEX'fk_classB_service_provider_classA1'('classA_id' ASC), 約束'fk_classB_service_provider_classA1' 外鍵('classA_id') 參考'amr'。'classA'('classA_id') ON DELETE NO ACTION ON UPDATE NO ACTION) – user1655798

+0

是的,我有單獨的休眠配置,但試圖維護一組數據庫腳本文件 – user1655798

回答

2

您已使用僅適用於MySQL的腳本。 下面的腳本應該是更多的跨數據庫,根據我的測試它適用於H2,MySQL和PostgreSQL(我沒有測試其他數據庫)。我還用INT替換了MySQL特定的INT(11)。腳本假設架構/數據庫amr已經存在:

drop table if exists amr.classB; 
drop table if exists amr.classA; 
CREATE TABLE IF NOT EXISTS amr.classA (
    classA_id INT(11) NOT NULL, 
    PRIMARY KEY (classA_id) 
); 
CREATE TABLE IF NOT EXISTS amr.classB ( 
    classB_id INT(11) NOT NULL , 
    name VARCHAR(45) NOT NULL , 
    classA_id INT(11) NOT NULL , 
    PRIMARY KEY (classB_id) 
); 
CREATE INDEX fk_classB_service_provider_classA1 
    ON amr.classA(classA_id ASC); 
ALTER TABLE amr.classB 
    ADD CONSTRAINT fk_classB_service_provider_classA1 
    FOREIGN KEY (classA_id) 
    REFERENCES amr.classA(classA_id) 
    ON DELETE NO ACTION ON UPDATE NO ACTION; 

然後,在Hibernate的配置,使用H2的H2模式。

相關問題