使用select语句锁定[SQLITE_BUSY]数据库文件

时间:2012-12-15 09:24:07

标签: java hibernate jpa sqlite

如果我针对我的网络应用运行多个线程,我会得到:

java.sql.SQLException: [SQLITE_BUSY]  The database file is locked (database is locked)
    at org.sqlite.DB.newSQLException(DB.java:383)
    at org.sqlite.DB.newSQLException(DB.java:387)
    at org.sqlite.DB.execute(DB.java:339)
    at org.sqlite.PrepStmt.executeQuery(PrepStmt.java:75)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)

我知道只有一个线程可以写入sqlite数据库,但我只是从数据库中读取。那么为什么我会收到此错误消息?

BTW:我的连接池如下所示:

<bean class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close" id="dataSource">
    <property name="driverClassName" value="${database.driverClassName}" />
    <property name="url" value="${database.url}" />
    <property name="username" value="${database.username}" />
    <property name="password" value="${database.password}" />
    <property name="initialSize" value="1" />
    <property name="maxActive" value="2" />
    <property name="maxIdle" value="1" />
    <property name="poolPreparedStatements" value="true" />
</bean>

设置为:Java 1.6,Tomcat 7.0.34,Spring 3.2,Hibernate 3.6.9和sqlite3 3.7.2

此致   罗杰

9 个答案:

答案 0 :(得分:17)

经过一些谷歌搜索后,我发现连接到SQLite时使用多个连接是一种不好的做法。参见

http://touchlabblog.tumblr.com/post/24474398246/android-sqlite-locking

将您的poolize maxactive设置为1并试用。

答案 1 :(得分:11)

应用程序应该只有一个连接。 你可以用它来确保。

public class SqliteHelper {
private static Connection c = null;
public static Connection getConn() throws Exception {
    if(c == null){
    Class.forName("org.sqlite.JDBC");
    c = DriverManager.getConnection("jdbc:sqlite:D:/test.db");
    }
    return c;
    }
}

答案 2 :(得分:5)

另请注意,如果您不小心忘记关闭连接,可能会发生这种情况:

Connection connection;
try {
  Statement statement = connection.createStatement();
  ResultSet resultSet = statement.executeQuery(QUERY);
  if (resultSet.next()) { /* do something */ }
catch (SQLException e) { /* handle exception */ }
finally {
  if (connection != null) {
    try {
      connection.close(); // <-- This is important
    } catch (SQLException e) {
      /* handle exception */
    }
  }
}

虽然启动服务器后第一个数据库连接可能运行良好,但后续查询可能不会,具体取决于连接池的配置方式。

答案 3 :(得分:1)

每次建立连接时务必在工作完成后关闭它,这对我有用 就像你正在使用

一样
Connection con = null;
PreparedStatement pst = con.prepareStatement("...query... "); 
/*
 do some stuff 
*/
pst.executeQuery();
pst.close();
con.close();

答案 4 :(得分:0)

对我来说,问题是我打开了太多的会话 因此,我将DAO类中的session字段设置为静态

答案 5 :(得分:0)

感谢鲍曼·汉(Bowman han),我在他的解决方案中添加了一段代码,并且对我有用。

private static Connection c = null;
public static Connection connect() throws Exception {

    if (c == null) {
        c = (Connection) DriverManager.getConnection(url);
    } else {
        c.close();
        c = (Connection) DriverManager.getConnection(url);
    }
    return c;
}

答案 6 :(得分:0)

我遇到了同样的问题,即使所有连接,结果集和语句都已关闭,但仍然出现错误。 我的问题是在Intellij中使用数据库浏览器插件来可视化和管理表。将数据库与该工具断开连接可以解决该问题。 因此,请确保没有外部工具正在连接到数据库和锁定表。

答案 7 :(得分:0)

就我而言,后台有线程使用sqlite连接,导致此错误。

  1. 关闭sqlitebrowser
  2. 关闭电子应用程序(可能需要重启)
  3. 重新运行您的程序。

答案 8 :(得分:-1)

对于仅执行读取的方法,请尝试@Transactional(readonly=true)。也许这适合你。