2016-08-17 2 views
0

Я получаю странное исключение, пытаясь проверить свой код, используя Встраиваемая СУБД H2:Получение JdbcBatchUpdateException при тестировании с Встраиваемая СУБД H2

java.lang.RuntimeException: 
java.lang.RuntimeException: org.h2.jdbc.JdbcBatchUpdateException: Timeout trying to lock table "CO_SCENARIO_1"; SQL statement: 
UPDATE CO_SCENARIO_1 SET VALUE = ? WHERE ATTRIBUTE = ? AND MODIFIER = ? [50200-156] 
    at de.telekom.skses.test.dao.DatabaseFileConverterTest.fromFile(DatabaseFileConverterTest.java:99) 

Это часть кода я пытаюсь тест:

case "overriddenVariables.txt": { 
         try (Scanner sc = new Scanner(bOut.toString())) { 
          try (Connection con = dataSource.getConnection()) { 
           String aQuery = "UPDATE $tableName SET VALUE = ? WHERE ATTRIBUTE = ? AND MODIFIER = ?"; 
           String line = ""; 
           if (sc.hasNext()) { 
            line = sc.nextLine(); 
           } 
           while (sc.hasNext()) { 
            if (line.startsWith("+")) { 
             String setting = line.substring(1); 
             try (PreparedStatement ps = con.prepareStatement(aQuery.replace("$tableName", setting))) { 

              while (sc.hasNext() && !(line = sc.nextLine()).startsWith("+")) { 
               int del1 = line.indexOf(":"); 
               int del2 = line.indexOf(':', del1 + 1); 
               String attr = line.substring(0, del1); 
               String modifier = line.substring(del1 + 1, del2); 
               String value = line.substring(del2 + 1, line.length()); 
               Clob myClob = con.createClob(); 
               myClob.setString(1, value); 
               ps.setClob(1, myClob); 
               ps.setString(2, attr); 
               ps.setString(3, modifier); 
               ps.addBatch(); 
              } 
              ps.executeBatch(); 
             } 

            } 
           } 

          } catch (SQLException e) { 
           logger.error("Error", e); 
           throw new RuntimeException(e); 
          } 
         } catch (Exception ex) { 
          logger.error("Error", ex); 
          throw new RuntimeException(ex); 
         } 

         break; 
        } 

StackOverflow говорит, что я должен установить таймаут блокировки, но я не нашел, как установить его для EmbeddedDatabase. Кроме того, в предыдущей версии я открыл новый PreparedStatement для каждого запроса и нового Connection для каждого PreparedStatement, все работало хорошо, и я не могу понять, почему это не так. Не могли бы вы объяснить, что мне нужно сделать, чтобы он снова работал?

Извините, если что-то не так, я новичок в Java EE.

ответ

1

Как я помню, используя H2 во встроенном режиме, он имеет проблемы с параллелизмом. вероятно, именно поэтому вы получаете таймаут для блокировки на столе, так как таблица по-прежнему обновляется с вашей последней партии при попытке выполнить следующую. При закрытии соединения и подготовленного состояния каждый раз время выполнения намного короче, поэтому вы не получите тайм-аут.

Вы пытались добавить в DatabaseURL ;MVCC=true, как указано в этом post? Если это не решит проблему, действительно ли необходимо использовать партии для вашего обновления?

EDIT: сообщение, которое я связал ранее, ссылки на h2 website где вы можете найти описание о том, как изменить тайм-аут блокировки, добавив ;LOCK_TIMEOUT=10000 к URL-адресу вашей базы данных. Это изменит его на 10 секунд, стандарт - 1 секунда

+0

Извините, но как я могу добавить эти параметры в EmbeddedDatabase? Я просто создаю autowire dataSource, созданный как '@Bean public EmbeddedDatabase dataSource() {return new EmbeddedDatabaseBuilder(). SetType (EmbeddedDatabaseType.H2) ... .build()}' –

+1

Хорошо, я просто много разобрался с этим, но если вы «Не используйте файлы spring.config, где вы указываете URL-адрес, я не знаю, возможно ли это. Только так я могу думать о том, где вы, возможно, обманываете его, делая то, что вы хотите, может использовать метод '.setName (" testDB; MVCC = true ")'. поскольку, как указано [здесь] (https://www.mkyong.com/spring/spring-embedded-database-examples/), Spring создает БД с помощью 'jdbc: h2: mem: testDb' в качестве URL-адреса, поэтому, возможно, позвонив DB 'testDB; MVCC = true' будет работать – LuckAss

+0

, вы могли бы назвать его в любом случае, если хотите, кстати, я просто использовал« testDb »;) – LuckAss