2015-08-28 102 views
1

我在Spring中使用HSQL數據庫時有一些不確定的行爲。有時,sequence會生成兩次,並且DataSource初始化會因此而失敗。HSQL數據庫偶爾會執行兩次schema.sql

奇怪的是,如果失敗,它總是從試圖讀取不存在的數據庫條目的測試中。讀取現有條目的其他測試不會失敗。

我真的不明白我做錯了什麼,爲什麼發生這種情況。

HSQLDB版本2.3.2

UPDATE: 我已刪除序列完全,現在我再次,偶爾得到錯誤正在創建兩倍表憑證。

這裏是我的配置:

@EnableJpaRepositories 
@EnableTransactionManagement 
@Configuration 
@Profile("test") 
public class TestDatabaseConfig { 

@Bean 
@Primary 
public EntityManagerFactory entityManagerFactory() throws ClassNotFoundException { 

    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 
    vendorAdapter.setGenerateDdl(false); 
    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); 
    factory.setJpaVendorAdapter(vendorAdapter); 
    factory.setPackagesToScan(ENTITIES_PACKAGE); 
    factory.setDataSource(dataSource()); 
    factory.afterPropertiesSet(); 
    return factory.getObject(); 

} 

@Bean 
@Primary 
public DataSource dataSource() { 

    return new EmbeddedDatabaseBuilder().addDefaultScripts() 
             .setType(EmbeddedDatabaseType.HSQL) 
             .build(); 
} 

@Bean 
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) throws ClassNotFoundException { 
    JpaTransactionManager txManager = new JpaTransactionManager(); 
    txManager.setEntityManagerFactory(entityManagerFactory); 
    return txManager; 
    } 
} 

而且schema.sql文件:

CREATE SEQUENCE voucher_id_seq AS INTEGER START WITH 100 INCREMENT BY 1; 
CREATE TABLE voucher (id INTEGER, code VARCHAR(64) NOT NULL UNIQUE, type VARCHAR(64) NOT NULL, state VARCHAR(64) NOT NULL, class_name VARCHAR(64), serial VARCHAR(64), consumption_user VARCHAR(255), creation_date TIMESTAMP DEFAULT current_timestamp, consumption_date TIMESTAMP, expiry_date TIMESTAMP) 

data.sql:

-- VALID 
INSERT INTO voucher (id, code, type, state, serial) VALUES (1,'success', '1', 'E', 'serial: 123'); 

--ALREADY CONSUMED 
INSERT INTO voucher (id, code, type, state) VALUES (2,'used', '1', 'U'); 

-- DATE EXPIRED 
INSERT INTO voucher (id, code, type, state, expiry_date) VALUES (3,'expired', '1', 'E', DATE '2014-12-12'); 

和錯誤跟蹤,在頂部,你可以看到序列有時會產生兩次:

引起:org.springframework.beans.BeanInstantiationException:無法實例化[javax.sql.DataSource]:工廠方法'dataSource'拋出異常;嵌套異常是org.springframework.jdbc.datasource.init.ScriptStatementFailedException:無法在資源類路徑資源[schema.sql]的第1行執行SQL腳本語句:CREATE SEQUENCE voucher_id_seq AS INTEGER START WITH 100 INCREMENT BY 1;嵌套異常是java.sql.SQLSyntaxErrorException:對象名已存在:語句中的VOUCHER_ID_SEQ [CREATE SEQUENCE voucher_id_seq AS INTEGER START WITH 100 INCREMENT BY 1] at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java: 189)〜[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)〜[spring-beans- 4.1.6.RELEASE.jar:4.1.6.RELEASE] ...省略了158個常用框架 引起的原因:org.springframework.jdbc.datasource.init.ScriptStatementFailedException:無法在資源類的第1行執行SQL腳本語句路徑資源[schema.sql]:CREATE SEQUENCE voucher_id_seq AS INTEGER START WITH 100 INCREMENT BY 1;嵌套異常是java.sql.SQLSyntaxErrorException:對象名已存在:語句中的VOUCHER_ID_SEQ [CREATE SEQUENCE voucher_id_seq AS INTEGER START WITH 100 INCREMENT BY 1] at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java: (資源數據庫管理器.java:208)〜[spring-jdbc- 4.0.9.RELEASE.jar:4.0.9.RELEASE] at org.springframework.jdbc.datasource.init.DatabasePopulatorUtils.execute(DatabasePopulatorUtils.java:49)〜[spring-jdbc-4.0.9.RELEASE.jar: 4.0.9.RELEASE] at org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory.initDatabase(EmbeddedDatabaseFactory.java:159)〜[spring-jdbc-4.0.9.RELEASE.jar:4.0.9.RELEASE] at org.springframework.jdbc .datasource.embedded.EmbeddedDatabaseFactory.getDatabase(EmbeddedDatabaseFactory.java:132)〜[spring-jdbc-4.0.9.RELEASE.jar:4.0.9.RELEASE] at org.springframework.jdbc.datasource。embedded.EmbeddedDatabaseBuilder.build(EmbeddedDatabaseBuilder.java:251)〜[spring-jdbc-4.0.9.RELEASE.jar:4.0.9.RELEASE] at com.siemens.ott.TestDatabaseConfig.dataSource(TestDatabaseConfig.java:46) 〜[test-classes /:na] at com.siemens.ott.TestDatabaseConfig $$ EnhancerBySpringCGLIB $$ 6a150586.CGLIB $ dataSource $ 1()〜[spring-core-4.1.6.RELEASE.jar:na] at com .siemens.ott.TestDatabaseConfig $$ EnhancerBySpringCGLIB $$ 6a150586 $$ FastClassBySpringCGLIB $$ 125e7bce.invoke()〜[spring-core-4.1.6.RELEASE.jar:na] at org.springframework.cglib.proxy.MethodProxy。 invokeSuper(MethodProxy.java:228)〜[spring-core-4.1.6.RELEASE.jar:4.1.6.RELEASE] at org.springframework.context.annotation.ConfigurationClassEnhancer $ BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:309) 〜[spring-context-4.1.6.RELEASE.jar:4.1.6.RELEASE] at com.siemens.ott.TestDatabaseConfig $$ EnhancerBySpringCGLIB $$ 6a150586.dataSource()〜[spring-core-4.1.6.RELEASE.jar:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)〜[ na:1.8.0_45] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)〜[na:1.8.0_45] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)〜[na: 1.8.0_45] at java.lang.reflect.Method.invoke(Method.java:497)〜[na:1.8.0_45] at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java: 162)〜[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] ...忽略159個常用幀 引起:java.sql.SQLSyntaxErrorException:對象名已存在:VOUCHER_ID_SEQ in stat ement [CREATE SEQUENCE voucher_id_seq AS INTEGER START WITH 100 INCREMENT BY 1] at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)〜[hsqldb-2.3.2.jar:2.3.2] at org.hsqldb.jdbc .JDBCUtil.sqlException(Unknown Source)〜[hsqldb-2.3.2.jar:2.3.2] at org.hsqldb.jdbc.JDBCStatement.fetchResult(Unknown Source)〜[hsqldb-2.3.2.jar:2.3.2 ] at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:[org.hsqldb.jdbc.JDBCStatement.execute(Unknown Source)〜[hsqldb-2.3.2.jar:2.3.2] ) 459)〜[彈簧JDBC-4.0.9.RELEASE.jar:4.0.9.RELEASE] ... 175個共同幀省略 所致:org.hsqldb.HsqlException:對象名已存在:VOUCHER_ID_SEQ

回答

0

對於任何其他可能會遇到這種情況的人來說,問題出在一種意想不到的地方:loader = AnnotationConfigWebContextLoader

@RunWith(SpringJUnit4ClassRunner.class) 
@WebAppConfiguration 
@ContextConfiguration(classes = { TestConfiguration.class }, loader = AnnotationConfigWebContextLoader.class) 
@ActiveProfiles("test") 
@TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class }) 

並簡單地刪除罪魁禍首解決了所有問題。 現在schema.sql只執行一次。