hibernate auto create in-memory hsqldb causes Sequence not found
I'm using hibernate as my jpa provider and want it to create a in-memory hsqldb on startup using: hibernate.hbm2ddl.auto=create
But for some reason I get exceptions like below in my logs. Things seems to work otherwise. Is it a hibernate or hsqldb problem?
I'm limited to using jpa 1 so I'm using hsqldb 1.8.0.10 and hibernate 3.3.0.SP1
This is similar to: Internal HSQL database complains about privileges
ERROR - 4. Statement.executeUpdate(drop sequence DDS_EMAIL_STATUS_SEQ) FAILED! drop sequence DDS_EMAIL_STATUS_SEQ {FAILED after 0 msec} java.sql.SQLException: Sequence not found in statement [drop sequence DDS_EMAIL_STATUS_SEQ] at org.hsqldb.jdbc.Util.sqlException(Unknown Source) at org.hsqldb.jdbc.jdbcStatement.fetchResult(Unknown Source) at org.hsqldb.jdbc.jdbcStatement.executeUpdate(Unknown Source) at net.sf.log4jdbc.StatementSpy.executeUpdate(StatementSpy.java:694) at org.apache.commons.dbcp.DelegatingStatement.executeUpdate(DelegatingStatement.java:228) at org.apache.commons.dbcp.DelegatingStatement.executeUpdate(DelegatingStatement.java:228) at org.hibernate.tool.hbm2ddl.SchemaExport.execute(SchemaExport.java:383) at org.hibernate.tool.hbm2ddl.SchemaExport.drop(SchemaExport.java:358) at org.hiber开发者_运维问答nate.tool.hbm2ddl.SchemaExport.execute(SchemaExport.java:258) at org.hibernate.tool.hbm2ddl.SchemaExport.create(SchemaExport.java:211) at org.hibernate.impl.SessionFactoryImpl.(SessionFactoryImpl.java:343) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1327) at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:867) at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:669) at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:132) at org.apache.openejb.assembler.classic.PersistenceBuilder.createEntityManagerFactory(PersistenceBuilder.java:184) at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:490) at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:450) at org.apache.openejb.assembler.classic.Assembler.buildContainerSystem(Assembler.java:368) at org.apache.openejb.assembler.classic.Assembler.build(Assembler.java:280) at org.apache.openejb.OpenEJB$Instance.(OpenEJB.java:125) at org.apache.openejb.OpenEJB$Instance.(OpenEJB.java:60) at org.apache.openejb.OpenEJB.init(OpenEJB.java:271) at org.apache.openejb.OpenEJB.init(OpenEJB.java:250) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.openejb.loader.OpenEJBInstance.init(OpenEJBInstance.java:36) at org.apache.openejb.client.LocalInitialContextFactory.init(LocalInitialContextFactory.java:71) at org.apache.openejb.client.LocalInitialContextFactory.init(LocalInitialContextFactory.java:53) at org.apache.openejb.client.LocalInitialContextFactory.getInitialContext(LocalInitialContextFactory.java:42) at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667) at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288) at javax.naming.InitialContext.init(InitialContext.java:223) at javax.naming.InitialContext.(InitialContext.java:197)
Since you're using an in-memory database, it's not surprising that a sequence, like any other database object, is not there at export time. But I don't know why you get a full stacktrace like this. I just tried with a basic test case and here is what I get:
16:27:07.708 [main] DEBUG o.h.tool.hbm2ddl.SchemaExport - Unsuccessful: drop sequence MY_ENTITY_SEQ 16:27:07.709 [main] DEBUG o.h.tool.hbm2ddl.SchemaExport - Sequence not found in statement [drop sequence MY_ENTITY_SEQ]
In other words, it "fails" silently.
Maybe you could try to extend the HSQLDialect
and override the following method:
protected String getDropSequenceString(String sequenceName) {
return "drop sequence " + sequenceName;
}
into:
protected String getDropSequenceString(String sequenceName) {
return "drop sequence " + sequenceName + " if exists";
}
Not tested though.
Here is a technique I like to use to get a fresh in-memory database each test.
@Override
public void setUp() throws Exception {
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory");
p.put("movieDatabase", "new://Resource?type=DataSource");
p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb" + System.currentTimeMillis());
p.put("openejb.embedded.initialcontext.close", "DESTROY");
initialContext = new InitialContext(p);
}
@Override
protected void tearDown() throws Exception {
initialContext.close();
}
Basically, give a unique database name by appending System.currentTimeMillis()
and rebuild the embedded container for each test.
Keeps you from having to cleanup after your tests yet doesn't require a new jvm for each test.
精彩评论