Si je lance plusieurs threads sur mon application Web, je reçois:
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)
Je sais qu'un seul thread peut écrire dans une base de données sqlite mais je ne fais que lire dans la base de données. Alors, pourquoi est-ce que je reçois ce message d'erreur?
BTW: Mon pool de connexion ressemble à ceci:
<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>
La configuration est la suivante: Java 1.6, Tomcat 7.0.34, Spring 3.2, Hibernate 3.6.9 et sqlite3 3.7.2.
Cordialement Roger
Après quelques recherches sur Google, j’ai trouvé que c’était une mauvaise pratique d’utiliser plusieurs connexions lors de la connexion à SQLite. Voir
http://touchlabblog.tumblr.com/post/24474398246/Android-sqlite-locking
Réglez votre pool maxactive à 1 et essayez-le.
Il ne devrait y avoir qu’UNE SEULE connexion avec votre application ... vous pouvez l’utiliser pour vous assurer.
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;
}
}
Notez également que cela peut se produire si vous oubliez accidentellement de fermer votre connexion:
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 */
}
}
}
Bien que la première connexion à la base de données puisse fonctionner correctement une fois le serveur démarré, les requêtes suivantes peuvent ne pas l'être, en fonction de la configuration du pool de connexions.
Chaque fois que vous établissez une connexion, assurez-vous de la fermer une fois le travail terminé. Cela a fonctionné pour moi comme si vous utilisiez
Connection con = null;
PreparedStatement pst = con.prepareStatement("...query... ");
/*
do some stuff
*/
pst.executeQuery();
pst.close();
con.close();
Pour moi, le problème était que j'ouvrais trop de sessions. J'ai donc rendu le champ de session statique dans ma classe DAO.