2012-04-20 5 views
2

У меня есть несколько методов, которые я сейчас пытаюсь выполнить модульные тесты. Эти методы работают отлично (в производстве) против DB2 v8 с использованием Spring JdbcTemplates.Синтаксис DB2 (предельное и грязное чтение) при запуске H2 (в режиме DB2)

Каждый SQL позволяет «грязные чтения» путем добавления «WITH UR» в оператор. Кроме того, некоторые из них используют «ограничение» путем добавления, например, «FETCH FIRST 1 ROWS ONLY».

Это отлично работает с реальной DB2, но я хочу, чтобы они тестировали эти методы против базы данных в памяти - это место, куда входит H2.

Все работает нормально, если я удаляю «WITH UR» и «FETCH FIRST ..», но я не хочу менять методы, но просто изменяю базу данных.

Насколько я вижу, это невозможно напрямую с помощью H2, поскольку синтаксис отличается (хотя я использую MODE = DB2).

Теперь, что делать? Должен ли я использовать другую базу данных в памяти? Я не хочу менять методы и не добавлять «тестовые» функции/хаки, так что это не-go.

Идеи, а также очень ценятся!

EDIT

Я не уверен, если это я или что, но я получаю следующее сообщение об ошибке. Обратите внимание: я использую Spring 3.1 и H2 1.3.166, а для базы данных - «jdbc: h2: ~/testdb; MODE = DB2». Я понятия не имею, почему он терпит неудачу, потому что SQL работает при запуске в консоли H2, но не из моего модульного тестирования (думаю, его не Н2, который разбивается):

Tests run: 3, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.109 sec <<< FAILURE! 
getAdvisor(impl.AdvisorServiceDaoImplTest) Time elapsed: 0.078 sec <<< ERROR! 
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT * FROM ADVISOR FETCH FIRST 1 ROWS ONLY ]; nested exception is org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "SELECT * FROM ADVISOR FETCH[*] FIRST 1 ROWS ONLY "; SQL statement: 
SELECT * FROM ADVISOR FETCH FIRST 1 ROWS ONLY [42000-166] 
    at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:233) 
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72) 
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:603) 
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:637) 
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:662) 
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:702) 
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.queryForObject(NamedParameterJdbcTemplate.java:178) 
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.queryForObject(NamedParameterJdbcTemplate.java:185) 
    at impl.AdvisorServiceDaoImpl.getAdvisor(AdvisorServiceDaoImpl.java:150) 
    at impl.AdvisorServiceDaoImplTest.getAdvisor(AdvisorServiceDaoImplTest.java:69) 
    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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83) 
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 
    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:300) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
    at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62) 
    at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140) 
    at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127) 
    at org.apache.maven.surefire.Surefire.run(Surefire.java:177) 
    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.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:338) 
    at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:997) 
Caused by: org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "SELECT * FROM ADVISOR FETCH[*] FIRST 1 ROWS ONLY "; SQL statement: 
SELECT * FROM ADVISOR FETCH FIRST 1 ROWS ONLY [42000-166] 
    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.message.DbException.getSyntaxError(DbException.java:181) 
    at org.h2.command.Parser.getSyntaxError(Parser.java:484) 
    at org.h2.command.Parser.prepareCommand(Parser.java:233) 
    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:1111) 
    at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:71) 
    at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:266) 
    at org.springframework.jdbc.core.PreparedStatementCreatorFactory$PreparedStatementCreatorImpl.createPreparedStatement(PreparedStatementCreatorFactory.java:245) 
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:581) 
    ... 40 more 

EDIT # 2 В случае, если кто-нибудь есть вот что я выяснил. Я использовал следующие:

<jdbc:embedded-database id="dataSource" type="H2"> 
    <jdbc:script location="classpath:sql/create_schemas.sql"/> 
    <jdbc:script location="classpath:sql/create_tables.sql"/> 
    <jdbc:script location="classpath:sql/create_test_data.sql"/> 
</jdbc:embedded-database> 

Это означает, что весна будет повторно создать экземпляр источника данных с общим боба, таким образом, мои настройки были потеряны. Решение (в моем случае) было просто загрузить базу данных программно с помощью следующих действий:

EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); 
EmbeddedDatabase db = builder.setName("salgdb").setType(EmbeddedDatabaseType.H2) 
      .addScript("sql/create_schemas.sql") 
      .addScript("sql/create_tables.sql") 
      .addScript("sql/create_test_data.sql") 
       .build(); 
+0

«FETCH FIRST 1 ROWS ONLY» должен работать с H2 ... можете ли вы опубликовать запрос, который вы используете, и версию H2, которую используете? Однако «WITH UR» не поддерживается. –

+0

Странно, казалось, не работает - думаю, мне придется попробовать еще раз. Итак, что мне делать с «WITH UR»? Есть идеи? – sunlock

+0

Забыл, моя версия 1.3.166 - и, похоже, она не работает. Я продолжаю получать ошибку. Я использую Spring JdbcTemplates, и он генерирует «плохую грамматику SQL». Если я удаляю «FETCH FIRST! ROWS ONLY», он работает как шарм ... – sunlock

ответ

5

Что вы можете сделать, это предоставить патч для базы данных H2, для поддержки функции «С UR» :-)

«FETCH FIRST 1 ROWS ONLY» уже работает с последней версией H2, но только в режиме DB2. Чтобы включить режим DB2, добавьте ;MODE=DB2 к URL базы данных, как в:

jdbc:h2:~/data/test;mode=db2 

Пример:

create table customer(id int); 
select * from customer fetch first 1 rows only; 

Я испытал это с H2 версии 1.3.166, но он также должен работать в старых версии, скорее всего, 1.3.161 и новее.Для того, чтобы проверить его вне весны:

  • Скачать H2 из http://h2database.com
  • Запустите инструмент H2 Console
  • Использование базы данных URL: jdbc:h2:~/temp/testdb;MODE=DB2
  • Выполнить заявления:

    create table ADVISOR(id int);

    SELECT * FROM ADVISOR FETCH FIRST 1 ROWS ONLY;

Я не получаю исключения, если я это сделаю.

+0

Я смотрю на источник, и это похоже на большую задачу, так что это не-go. Хотя было бы неплохо :) – sunlock

+0

Возможно, проблема в том, что вы используете более старую версию H2? Я обновил свой ответ. –

+0

Я обновил свой вопрос. Я получаю эту ошибку от H2, 42000-166, но google не помогает. – sunlock