JDBC sqlite database locked error

时间:2017-12-18 08:32:18

标签: java sqlite jdbc junit

I have a problem with my JDBC SQLite database: when trying to drop the tables I get the error saying that a table is locked. The strange thing is that I get different results with the same code on different places. I know this question is already asked here, but I close all my resultsets and (prepared)statements.

This is my OfflineDB.java file:

public String sendMessage(String processInstanceId) {
        WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
        String request = "<SOAP:Envelope xmlns:" + "SOAP='http://schemas.xmlsoap.org/soap/envelope/'>" + "<SOAP:Body>"
                + "<SendMessage xmlns='http://schemas.cordys.com/bpm/execution/1.0'>" + "<receiver>" + processInstanceId
                + "</receiver>" + "<message overwrite='false' />" + "</SendMessage>" + "</SOAP:Body>"
                + "</SOAP:Envelope>";
        SendMessageAPI sendMessageObject = new SendMessageAPI();
        StreamSource source = new StreamSource(new StringReader(request));
        StreamResult result = new StreamResult(System.out);
        System.out.println("called service" + request);
        webServiceTemplate.sendSourceAndReceiveToResult(
                "url",
                source, result);
        return "Success";

Simple: it just opens a connection on creation and stores this connection.

I have a JUnit test for this class, and this test runs perfectly:

public enum OfflineDB {

    UNIQUEINSTANCE;

    private Connection conn = null;

private OfflineDB(){
    try {
        System.out.println("Working Directory = " +
          System.getProperty("user.dir"));
        conn = DriverManager.getConnection("jdbc:sqlite:" + 
                System.getProperty("user.dir") + "\\database.db"); 
        setupDB();
    } catch (SQLException e) {
        System.err.println(e.getMessage());
    }
}
public Connection getConnection(){
    return conn;
}
public void setupDB(){
    Statement stmt = null;
    try {
        stmt = conn.createStatement();
        stmt.closeOnCompletion();
        stmt.execute(CREATE_CAR);
        stmt.execute(CREATE_DTTS);
        stmt.execute(CREATE_CHDT);
        stmt.execute(CREATE_USER);
        stmt.execute(CREATE_CIRCUIT);
        stmt.execute(CREATE_CSD);
        stmt.execute(CREATE_DASHBOARD);
        stmt.execute(CREATE_ICW);
        stmt.execute(CREATE_TILE);
        stmt.execute(CREATE_TSD);
        stmt.execute(CREATE_ISUPDATED);
        stmt.close();

    } catch (SQLException ex) {
        ex.printStackTrace();
    } finally{
        try {
            stmt.close();
        } catch (SQLException | NullPointerException e) {
            e.printStackTrace();
        }
    }
}
public boolean dropTables(){
    Statement stmt = null;
    try {
        stmt = conn.createStatement();
        stmt.closeOnCompletion();
        stmt.execute(DROP_DTTS);
        stmt.execute(DROP_CHDT);

        stmt.execute(DROP_TSD);
        stmt.execute(DROP_CSD);
        stmt.execute(DROP_ICW);
        stmt.execute(DROP_CAR);
        stmt.execute(DROP_CIRCUIT);
        stmt.execute(DROP_DASHBOARD);
        stmt.execute(DROP_TILE);
        stmt.execute(DROP_USER);
        stmt.execute(DROP_ISUPDATED);
        stmt.close();
    } catch (SQLException ex) {
        ex.printStackTrace();
        System.out.println(ex.getErrorCode());
        return false;
    } finally{
        try {
            stmt.close();
        } catch (SQLException | NullPointerException e) {
            e.printStackTrace();
        }
    }
    return true;
}

In another class I try to run the same code as this test, but here I get the error saying that the database is locked:

@Test
public void testDropTables(){
    Boolean bool = OfflineDB.UNIQUEINSTANCE.dropTables();
    assertTrue(bool);
}

I also wrote a JUnit for this and when I try to run the test, the error occurs, if I immediately run the previous test after this one, this gives no problem.

public boolean syncDatabases(){
    if(!checkIsUpdated()) return false;
    else{
        System.out.println("syncing databases");
        if(!OfflineDB.UNIQUEINSTANCE.dropTables()) return false;
    }
    return true;
}

public boolean checkIsUpdated(){
    boolean updateNeeded = false;
    //check if the online timestamp is later than the offline
    Timestamp online = getLastUpdated(true);
    Timestamp offline = getLastUpdated(false);
    System.out.println("online: " + online + " offline: " + offline);
    if(getLastUpdated(true).after(getLastUpdated(false))) 
        updateNeeded = true;
    return updateNeeded;
}

The error:

@Test
public void testSyncDatabases() {
    System.out.println("syncDatabases");
    boolean expResult = true;
    boolean result = SyncMapper.UNIQUEINSTANCE.syncDatabases();
    assertEquals(expResult, result);
}

1 个答案:

答案 0 :(得分:1)

显然我错了:还有一个结果集没有关闭......对于将来遇到同样问题的人:请确保在返回后不关闭结果集或准备好的结果。在我的情况下,我在try / catch中的if / else结构中返回了一个时间戳,然后在if / else之后我关闭了resultset和preparedstatement,这导致代码永远不会到达这些行。