我正在使用Android上的数据库连接工厂进行一些测试。
public class ConnectionFactory {
private Context context;
private SQLiteDatabase w;
private static DatabaseManager manager;
public ConnectionFactory(Context context) {
this.context = context;
}
public synchronized SQLiteDatabase getDatabase(){
if(manager == null){
DatabaseManager.init(new DatabaseHelper(context));
manager = DatabaseManager.getInstance();
}
return w == null || !w.isOpen() ? w = manager.getDatabase() : w;
}
public synchronized void close() {
if(w != null && w.isOpen()){
manager.close();
}
}
}
我的DatabaseManager(我为同时访问数据库的场景创建了这个类)
public class DatabaseManager {
private static SQLiteOpenHelper helper;
private static DatabaseManager instance;
private static int COUNTER = 0;
private SQLiteDatabase database;
private DatabaseManager(){}
public static synchronized void init(SQLiteOpenHelper first) {
if (instance == null) {
helper = first;
instance = new DatabaseManager(){
@Override
protected void finalize() throws Throwable {
helper.close();
COUNTER = 0;
helper = null;
}
};
}
}
public static synchronized DatabaseManager getInstance() {
if (instance == null) {
throw new IllegalStateException("O método init deve ser chamado antes deste método.");
}
return instance;
}
public synchronized SQLiteDatabase getDatabase() {
COUNTER++;
if(COUNTER == 1) {
Log.i("SIAEP", "====================== ABRINDO UMA NOVA REFERENCIA DE SQLITEDATABASE ======================");
database = helper.getWritableDatabase();
}
Log.i("SIAEP", "====================== DATABASE MANAGER COUNTER 'getDatabase': "+ COUNTER +" ======================");
return database;
}
public synchronized void close() {
if(COUNTER != 0)
COUNTER--;
if(COUNTER == 0) {
if(database.inTransaction()){
database.endTransaction();
}
Log.i("SIAEP", "====================== FECHANDO A REFERENCIA DE SQLITEDATABASE ======================");
database.close();
}
Log.i("SIAEP", "====================== DATABASE MANAGER COUNTER 'close': "+ COUNTER +" ======================");
}
}
我的测试课程:
public class TesteActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Worker t1 = new Worker(this);
Worker t2 = new Worker(this);
t1.start();
t2.start();
}
public static class Worker extends Thread {
private Activity instance;
public Worker(Activity instance) {
this.instance = instance;
}
@Override
public void run() {
ConnectionFactory factory = new ConnectionFactory(instance);
for (int i = 0; i < 100; i++) {
SQLiteDatabase database = factory.getDatabase();
factory.close();
}
}
}
}
这很有效,但是当我使用交易时,我会收到一些例外情况:
@Override
public void run() {
ConnectionFactory factory = new ConnectionFactory(instance);
for (int i = 0; i < 100; i++) {
SQLiteDatabase database = factory.getDatabase();
database.beginTransaction();
database.setTransactionSuccessful();
database.endTransaction();
factory.close();
}
}
EXCETION:
E / ACRA(9850):java.lang.IllegalStateException:尝试重新打开 一个已经关闭的对象:SQLiteDatabase: /data/data/seduc.ma.com.br.siaepmovel/databases/database.sqlite E / ACRA (9850):at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55) E / ACRA(9850):at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:503) E / ACRA(9850):at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:416) E / ACRA(9850):at seduc.ma.com.br.siaepmovel.test.TesteActivity $ Worker.run(TesteActivity.java:45)
任何想法为什么?
====
我的问题不同,因为问题只发生在交易中。
答案 0 :(得分:0)
在您的代码中,您只有一个对数据库对象的引用。如果其中一个工人调用close方法,则其他工作人员不能使用封闭连接。你应该一个接一个地打电话给工人。您应该在班级 ConnectionFactory
中清除上下文参考查看http://orientdb.com/docs/2.0/orientdb.wiki/Graph-Database-Tinkerpop.html#using-indices