3

I have create a java software which make use of sqlite database. The whole database works smoothly however after some time of running the application I am reveiving the following message (from a try catch block):

java.sql.SQLException: [SQLITE_BUSY] The database file is locked (database is locked)

I ve solved my problems by closing the software every time the exception rising. However is there a way to close my database instead so as not to close the software every time?

I ve got plenty of queries however my prob arises always in a specific point:

        try {
            String query = "select * from StudentsSession where userId=? and course=? and level=?";
            PreparedStatement pst = connectionUsers.prepareStatement(query);
            pst.setString(1, saveUser.getText());
            pst.setString(2, textSubjectQTest);
            st.setString(3, showCurrentLevelLabel.getText());
            ResultSet rs = pst.executeQuery();
            while (rs.next()) {
                count = count + 1;
            }
            pst.close();
            rs.close();

        } catch (Exception a) {
            System.out.println(a);
        }
        try {
            String countS, tmpS;
            countS = String.valueOf(count);
            sessionId.setText(countS);
            long unixTime = System.currentTimeMillis() / 1000L;
            tmpS = String.valueOf(unixTime);
            date.setText(tmpS);
            course.setText(textSubjectQTest);

            String query = "insert into StudentsSession (userId,date,course,level,trial,score) values (?,?,?,?,?,-1)";
            PreparedStatement pst = connectionUsers.prepareStatement(query);
            pst.setString(1, saveUser.getText());
            pst.setString(2, tmpS);
            pst.setString(3, textSubjectQTest);
            pst.setString(4, showCurrentLevelLabel.getText());
            pst.setString(5, countS);
            pst.executeUpdate();
            pst.close();

        } catch (Exception a) {

            System.out.println(a);
            System.exit(0);
        }

        String file1 = "";
        ResultSet ts4;
        try {

            sessionId3 = "";
            String query3 = "select * from studentssession where userid = ?  and course = ? and level = ?";
            PreparedStatement pst__1 = connectionUsers.prepareStatement(query3);
            pst__1.setString(1, saveUser.getText());
            pst__1.setString(2, textSubjectQTest);
            pst__1.setString(3, showCurrentLevelLabel.getText());
            ts4 = pst__1.executeQuery();

            while (ts4.next()) {
                sessionId3 = ts4.getString("sessionId");
            }
            pst__1.close();
            ts4.close();
            obj = new CaptureVideoFromWebCamera();

            file1 = "videos/" + userTextFieldS.getText();

            file1 = file1 + "_" + sessionId3;
            file1 = file1 + ".wmv";

            obj.start(file1);

        } catch (Exception e4) {
            e4.getCause();
        }

Sometimes this code rise the exception.

Jose Ramon
  • 5,572
  • 25
  • 76
  • 152
  • SQlite is useful for small local application, in that case, a Singleton is enough to prevent a lock. If you have multiple thread in you application, that will resolve your issues. I would say that you forgot to close you connection somewhere. I used it on an old app without having this kind off issues. – AxelH Sep 15 '16 at 12:17
  • It seems that this error arise when I am trying to have access to a specific table. So my problem is that I have a query statement I never closed it somewhere? – Jose Ramon Sep 15 '16 at 12:18
  • My problem arises in a specific query every time, I am not sure why! – Jose Ramon Sep 15 '16 at 12:50
  • I tried it in sqlite browser and it works. Maybe since I am using a lot of times the table during my software session somewhere the table remains open. – Jose Ramon Sep 15 '16 at 13:26
  • You could use it 1 billion time, if you close the I/O correctly, there is no issue with it. Could you add more code, if you use a transaction, how do you manage exception in the query, if you close everything... – AxelH Sep 15 '16 at 13:49
  • I edit my question with code. – Jose Ramon Sep 15 '16 at 13:53
  • I also observed that if you are running a Java Program with SELECT queries and you have any other SQL Editor open, in which you are trying to insert records, even then the SQLite file gets locked and shows this BUSY message. Solution is to CLOSE the SQL Editor so that file lock count goes back to 0 and use proper ResultSet and PreparedStatement close code in the Java program. – Rahul Saini Jul 21 '17 at 10:39

3 Answers3

4

Every time you open a connection with the SQLite database, make sure to close the database connection after you process the results or etc. if you already have an open connection to the database and if you try to get the connection again and try some Update or Insert queries, the system will not give the permission and will raise an error.

dilanSachi
  • 562
  • 6
  • 14
1

Sorta duplicate of existing question, but this is a good starting point. Because SQLite is just a library that reads and writes to a file on the file system, not a full SQL database, you should really only have one connection open to it at a time. Otherwise it is pretty easy to get into a race condition.

For local testing, it should be fine, but for a system of any complexity expecting multiple users, you should be using something like Postgre or MySQL.

Community
  • 1
  • 1
Mike Thomsen
  • 36,828
  • 10
  • 60
  • 83
  • Yes I am aware about that. However sometimes the problem happerning just by running just one instance of my software. I have several select insert and update queries though. The problem arise in a specific table. Can I control somehow the access to that table of my database? – Jose Ramon Sep 15 '16 at 12:14
  • Using MySql for an application necessite to install it, not the best choice if you just want to be able to store in local file some data using the SQL syntax. – AxelH Sep 15 '16 at 12:18
1

Your try catch are wrong, you try to close the ResultSet and Statemnt in the try block instead of a finally block. This could lead to leaks.

You should do it like this, in the finally.

PreparedStatement pst  = null;
ResultSet rs = null;
try {
        pst = connectionUsers.prepareStatement(query);
        ...  
        rs = pst.executeQuery();
        ...                    
    } catch (Exception a) {
        a.printStackTrace();
    } finally {
        if(rs != null){
             try{
                  rs.close();
             } catch(Exception e){
                 e.printStackTrace();
             }
        }
        if(pst != null){
            try{
                pst.close();
            } catch(Exception e){
                e.printStackTrace();
            }
        }
    }

Or you could look to the Try-with-resource.

This could be a reason.

AxelH
  • 14,325
  • 2
  • 25
  • 55
  • So should I do the same for every query I ve got in my code? – Jose Ramon Sep 15 '16 at 14:02
  • If this is not the reason, then the `connectionUser` could be the cause. (the name is not reassuring, since you should have only 1 connection for the entire application) – AxelH Sep 15 '16 at 14:03
  • Is there a way to retrieve what exactly cause my issue? – Jose Ramon Sep 15 '16 at 14:04
  • @JoseRamon, Oh yes, if an exception occurs, you never close the resultset or statement. This is a common error that you should correct. – AxelH Sep 15 '16 at 14:04
  • For the exact cause, you should be more specific on the test you have done to make it crash, where in this block of 4 query. I can only assume on the cause without every information ;) – AxelH Sep 15 '16 at 14:10
  • My problem rising in the catch that I ve got also the system.exit :) – Jose Ramon Sep 15 '16 at 14:25
  • Well, is it really a correct usage to exit here ? It's a bit brutal I think ;) – AxelH Sep 15 '16 at 14:45
  • Yea in my case is better to close the application than having empty fields in my database. – Jose Ramon Sep 15 '16 at 14:58
  • Well, close everything then exit the app (not sure a leak in Java could remain after the end the main thread but better safe than sorry), don't forget the connectionUser! – AxelH Sep 16 '16 at 06:36