是否有可能丢失 SQLite 数据库连接?
Is it possible to lose a SQLite database connection?
我在 Android 应用中看到很少 "java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed."
异常。我在很多地方都没有关闭连接。连接也可能在其他线程中关闭。
请确认一下,SQLite 连接是否可能自动关闭或由操作系统关闭或隐式关闭?
是 - 任何数据库连接都可以在您背后关闭。如果 dba 决定终止您的连接,它可能发生在服务器端。如果超时,它可能会在客户端发生。由于各种原因,它可能发生在 jdbc 内。它甚至可能在您的代码中意外发生。
虽然这里有些含糊不清。您报告 无法执行此操作,因为连接 池 已关闭。您的连接池不太可能在您不知情的情况下关闭。此外,如果您正确使用连接池,它将在关闭时重新打开 数据库 连接。
我只遇到过以下几种情况:
- 您关闭了与数据库的连接,而不是关闭游标
IE:
SQLiteDatabase db = getReadableDatabase();
//Read Operations
//process cursor
db.close(); //closes entire database connection and cursor is invalid throwing an error
调用 activity 上下文不再有效
这个source recommends you to use a singleton DatabaseHelper, and some do not demonify it.
这向我表明,数据库不应在您的应用程序的生命周期内简单地自行关闭。
第一个来源@Alex Lockwood
Approach #1: Use a Singleton to Instantiate the SQLiteOpenHelper
Declare your database helper as a static instance variable and use the
Singleton pattern to guarantee the singleton property. The sample code
below should give you a good idea on how to go about designing the
DatabaseHelper class correctly.
The static getInstance() method ensures that only one DatabaseHelper
will ever exist at any given time. If the sInstance object has not
been initialized, one will be created. If one has already been created
then it will simply be returned. You should not initialize your helper
object using with new DatabaseHelper(context)! Instead, always use
DatabaseHelper.getInstance(context), as it guarantees that only one
database helper will exist across the entire application's lifecycle.
第二来源@CommonsWare
Having a single SQLiteOpenHelper instance can help in threading cases.
Since all threads would share the common SQLiteDatabase,
synchronization of operations is provided.
这是我的亲身经历。
在我将我的代码应用到臭名昭著的单例 SQLİteOpenHelper 方法之后,事情变得更好了,因为助手对象会同步该对象上的所有数据库访问。但是,它仍然不是最好的。
看,所有这些同步内容都不是真正的原子,它们发生在您无法控制的区域。因此,假设就在您查询之前,连接可能已被其他拥有锁的线程关闭。
您可以在查询之前检查连接,但如果连接已关闭怎么办?你跳过做你需要做的事?或者您在您拥有控制权的级别为您的特定数据库访问中心实施简单的同步?我肯定会选择第二种方式。
我在 Android 应用中看到很少 "java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed."
异常。我在很多地方都没有关闭连接。连接也可能在其他线程中关闭。
请确认一下,SQLite 连接是否可能自动关闭或由操作系统关闭或隐式关闭?
是 - 任何数据库连接都可以在您背后关闭。如果 dba 决定终止您的连接,它可能发生在服务器端。如果超时,它可能会在客户端发生。由于各种原因,它可能发生在 jdbc 内。它甚至可能在您的代码中意外发生。
虽然这里有些含糊不清。您报告 无法执行此操作,因为连接 池 已关闭。您的连接池不太可能在您不知情的情况下关闭。此外,如果您正确使用连接池,它将在关闭时重新打开 数据库 连接。
我只遇到过以下几种情况:
- 您关闭了与数据库的连接,而不是关闭游标
IE:
SQLiteDatabase db = getReadableDatabase();
//Read Operations
//process cursor
db.close(); //closes entire database connection and cursor is invalid throwing an error
调用 activity 上下文不再有效
这个source recommends you to use a singleton DatabaseHelper, and some do not demonify it.
这向我表明,数据库不应在您的应用程序的生命周期内简单地自行关闭。
第一个来源@Alex Lockwood
Approach #1: Use a Singleton to Instantiate the SQLiteOpenHelper
Declare your database helper as a static instance variable and use the Singleton pattern to guarantee the singleton property. The sample code below should give you a good idea on how to go about designing the DatabaseHelper class correctly.
The static getInstance() method ensures that only one DatabaseHelper will ever exist at any given time. If the sInstance object has not been initialized, one will be created. If one has already been created then it will simply be returned. You should not initialize your helper object using with new DatabaseHelper(context)! Instead, always use DatabaseHelper.getInstance(context), as it guarantees that only one database helper will exist across the entire application's lifecycle.
第二来源@CommonsWare
Having a single SQLiteOpenHelper instance can help in threading cases. Since all threads would share the common SQLiteDatabase, synchronization of operations is provided.
这是我的亲身经历。
在我将我的代码应用到臭名昭著的单例 SQLİteOpenHelper 方法之后,事情变得更好了,因为助手对象会同步该对象上的所有数据库访问。但是,它仍然不是最好的。
看,所有这些同步内容都不是真正的原子,它们发生在您无法控制的区域。因此,假设就在您查询之前,连接可能已被其他拥有锁的线程关闭。
您可以在查询之前检查连接,但如果连接已关闭怎么办?你跳过做你需要做的事?或者您在您拥有控制权的级别为您的特定数据库访问中心实施简单的同步?我肯定会选择第二种方式。