2016-08-17 1 views
0

ich seltsame Ausnahme bekommen versucht, meinen Code zu testen H2 mit Eingebettetes Datenbanksystem:Erste JdbcBatchUpdateException während mit H2 Eingebettetes Datenbanksystem zu testen

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) 

Dies ist Teil des Codes zu testen ich versuche:

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 sagt, dass ich Sperrzeitlimit setzen sollte, aber ich habe nicht gefunden, wie man es für EmbeddedDatabase einstellt. Außerdem habe ich in der vorherigen Version neue PreparedStatement für jede Abfrage und neue Verbindung für jede PreparedStatement geöffnet, alles hat gut funktioniert, und ich kann nicht verstehen, warum es jetzt nicht tut. Können Sie mir bitte erklären, was ich tun muss, damit es wieder funktioniert?

Sorry, wenn etwas nicht stimmt, ich bin neu in Java EE.

Antwort

1

Wenn ich mich erinnere, H2 im Embedded-Modus zu verwenden, hat es Probleme mit Nebenläufigkeit. Dies ist wahrscheinlich der Grund, warum Sie das Zeitlimit für die Sperre für die Tabelle erhalten, da die Tabelle immer noch von Ihrem letzten Stapel aktualisiert wird, wenn Sie versuchen, den nächsten auszuführen. Wenn Sie die Verbindung und preparedStatement jedes Mal schließen, ist die Ausführungszeit viel kürzer, so dass Sie die Zeitüberschreitung nicht erhalten.

Haben Sie versucht, die DatabaseURL ;MVCC=true wie in dieser post angegeben hinzuzufügen? Wenn das Problem dadurch nicht gelöst wird, ist es wirklich notwendig, Chargen für Ihr Update zu verwenden?

BEARBEITEN: der Beitrag, den ich zuvor verlinkt habe, Links zum h2 website, wo Sie eine Beschreibung finden, wie Sie das Sperrzeitlimit ändern, indem Sie ;LOCK_TIMEOUT=10000 zu Ihrer Datenbank-URL hinzufügen. Dies würde es in 10 Sekunden ändern, Standard ist 1 Sekunde

+0

Sorry, aber wie kann ich diese Einstellungen zu EmbeddedDatabase hinzufügen? Ich Autowire nur DataSource erstellt wie '@Bean öffentliche EmbeddedDatabase dataSource() {neue EmbeddedDatabaseBuilder() zurückgeben. SetType (EmbeddedDatabaseType.H2) ... .build()}' –

+1

Ok ich nur googled viel darüber, aber wenn Sie Verwenden Sie keine spring.config-Dateien, in denen Sie die URL angeben, die ich nicht weiß, ob dies möglich ist. Ich kann mir nur vorstellen, wo Sie es vielleicht hinbekommen, um das zu tun, was Sie wollen, indem Sie die Methode '.setName (" testDB; MVCC = true ") verwenden. Da wie hier [hier] (https://www.mkyong.com/spring/spring-embedded-database-examples/) Spring erstellt die DB mit 'jdbc: h2: mem: testDb' als URL, also vielleicht durch den Aufruf der DB 'testDB; MVCC = true' es wird funktionieren – LuckAss

+0

du könntest es trotzdem benennen, du willst es übrigens, ich habe einfach" testDb "benutzt;) – LuckAss