我正在尝试使用ddl auto create使用hsqldb设置一个简单的Spring上下文。这仅适用于单元测试,因为在生产中我们使用的是postgresql。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:mem:unittest;sql.syntax_pgs=true" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<bean id="entityManagerFactoryBean" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.foo.service.analytics.google" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.archive.autodetection">class,hbm</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryBean" />
</bean>
<bean class="com.foo.service.analytics.google.GaDimensionDaoImpl" />
<bean class="com.foo.service.analytics.google.GaHibernateAdapterImpl" />
<context:annotation-config />
</beans>
根据日志创建数据库成功:
Hibernate: drop table analytics.dim_date if exists
Hibernate: drop sequence seq_dim_location_sequence
Hibernate: create table analytics.dim_date (dim_date_id integer not null, date timestamp, hour integer, minute integer, primary key (dim_date_id))
Hibernate: create sequence seq_dim_location_sequence
这是我的实体:
package com.foo.service.analytics.google.dimensions;
import com.foo.service.analytics.google.DimensionAttribute;
import com.foo.service.analytics.google.GaDimensionDao;
import javax.persistence.*;
import java.util.Calendar;
@Entity
@NamedQueries({
@NamedQuery(
name = GaDimensionDao.GET_BY_DIM_ATTRIBUTES,
query = "SELECT dim FROM DateDimension dim " +
"WHERE dim.date = :date " +
"AND (:hour IS NULL OR dim.hour = :hour) " +
"AND (:minute IS NULL OR dim.minute = :minute)"
)
})
@SequenceGenerator(name = "seq_dim_location", sequenceName = "seq_dim_location_sequence",
schema = "analytics", allocationSize = 1)
@Table(name = "dim_date", schema = "analytics")
public class DateDimension {
@Id
@Column(name = "dim_date_id", nullable = false)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_dim_location")
private Integer id;
@Column(name = "date")
private Calendar date;
@Column(name = "hour")
private Integer hour;
@Column(name = "minute")
private Integer minute;
}
使用NamedQuery后,我得到以下stacktrace:
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: user lacks privilege or object not found: DIM_DATE in statement [select datedimens0_.dim_date_id as dim1_0_, datedimens0_.date as date0_, datedimens0_.hour as hour0_, datedimens0_.minute as minute0_ from analytics.dim_date datedimens0_ where datedimens0_.date=? and (? is null or datedimens0_.hour=?) and (? is null or datedimens0_.minute=?) limit ?]
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1367)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1295)
at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:317)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:360)
at com.sun.proxy.$Proxy30.getSingleResult(Unknown Source)
at com.foo.service.analytics.google.GaDimensionDaoImpl.createOrGet(GaDimensionDaoImpl.java:50)
at com.foo.service.analytics.google.GaHibernateAdapterImpl.processRow(GaHibernateAdapterImpl.java:79)
at com.foo.service.analytics.google.GaHibernateAdapterImpl.convert(GaHibernateAdapterImpl.java:40)
at com.foo.service.analytics.google.GaHibernateAdapterTest.createHibernateObjectFromGaTest(GaHibernateAdapterTest.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:72)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:81)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:216)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:82)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:60)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:67)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:162)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
Caused by: org.hibernate.exception.SQLGrammarException: user lacks privilege or object not found: DIM_DATE in statement [select datedimens0_.dim_date_id as dim1_0_, datedimens0_.date as date0_, datedimens0_.hour as hour0_, datedimens0_.minute as minute0_ from analytics.dim_date datedimens0_ where datedimens0_.date=? and (? is null or datedimens0_.hour=?) and (? is null or datedimens0_.minute=?) limit ?]
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:82)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
at org.hibernate.engine.jdbc.internal.proxy.ConnectionProxyHandler.continueInvocation(ConnectionProxyHandler.java:146)
at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
at com.sun.proxy.$Proxy31.prepareStatement(Unknown Source)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:147)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:166)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:145)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1711)
at org.hibernate.loader.Loader.doQuery(Loader.java:828)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:289)
at org.hibernate.loader.Loader.doList(Loader.java:2438)
at org.hibernate.loader.Loader.doList(Loader.java:2424)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2254)
at org.hibernate.loader.Loader.list(Loader.java:2249)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:470)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:355)
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:195)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1248)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)
at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:284)
... 37 more
Caused by: java.sql.SQLSyntaxErrorException: user lacks privilege or object not found: DIM_DATE in statement [select datedimens0_.dim_date_id as dim1_0_, datedimens0_.date as date0_, datedimens0_.hour as hour0_, datedimens0_.minute as minute0_ from analytics.dim_date datedimens0_ where datedimens0_.date=? and (? is null or datedimens0_.hour=?) and (? is null or datedimens0_.minute=?) limit ?]
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCPreparedStatement.<init>(Unknown Source)
at org.hsqldb.jdbc.JDBCConnection.prepareStatement(Unknown Source)
at org.apache.commons.dbcp.DelegatingConnection.prepareStatement(DelegatingConnection.java:281)
at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.prepareStatement(PoolingDataSource.java:313)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.hibernate.engine.jdbc.internal.proxy.ConnectionProxyHandler.continueInvocation(ConnectionProxyHandler.java:138)
... 55 more
Caused by: org.hsqldb.HsqlException: user lacks privilege or object not found: DIM_DATE
at org.hsqldb.error.Error.error(Unknown Source)
at org.hsqldb.error.Error.error(Unknown Source)
at org.hsqldb.ParserDQL.readTableName(Unknown Source)
at org.hsqldb.ParserDQL.readTableOrSubquery(Unknown Source)
at org.hsqldb.ParserDQL.XreadTableReference(Unknown Source)
at org.hsqldb.ParserDQL.XreadFromClause(Unknown Source)
at org.hsqldb.ParserDQL.XreadTableExpression(Unknown Source)
at org.hsqldb.ParserDQL.XreadQuerySpecification(Unknown Source)
at org.hsqldb.ParserDQL.XreadSimpleTable(Unknown Source)
at org.hsqldb.ParserDQL.XreadQueryPrimary(Unknown Source)
at org.hsqldb.ParserDQL.XreadQueryTerm(Unknown Source)
at org.hsqldb.ParserDQL.XreadQueryExpressionBody(Unknown Source)
at org.hsqldb.ParserDQL.XreadQueryExpression(Unknown Source)
at org.hsqldb.ParserDQL.compileCursorSpecification(Unknown Source)
at org.hsqldb.ParserCommand.compilePart(Unknown Source)
at org.hsqldb.ParserCommand.compileStatement(Unknown Source)
at org.hsqldb.Session.compileStatement(Unknown Source)
at org.hsqldb.StatementManager.compile(Unknown Source)
at org.hsqldb.Session.execute(Unknown Source)
... 64 more
从schema
注释中删除@Table
值可以使此操作成功。我在生成的ddl语句以及stacktrace中的查询中看到了模式创建。是否还需要做其他事情才能使用hsqldb启用模式而不更改绑定本身?
供参考,我使用的是Spring 4.1.1.Release,hsqldb 2.3.4和Hibernate 4.1.3.Final。
更新 通过在this answer中所述的INIT参数中手动创建模式,我确实通过从HSQLDB切换到H2来实现我的目标。保持这个问题,以防有人得到HSQLDB的答案,因为我无法在任何地方找到解决方案。