Androidデータベース接続の解決方法、sqlite 3 database is lockedを避ける

4375 ワード

1.説明
Androidのsqlite 3データベースでは、データベースロックのメカニズムの問題で、同じデータベースに対して同時に書き込み操作ができないため、database is lockedのエラーが爆発する可能性があります.
ネット上の資料を総合して、単例のモードを使って、全局は1つの接続を維持するのが比較的に実用的だと思っています;
2.具体コード
まず、データベースに具体的に接続するコードは次のとおりです.
public class DataBaseOpenHelper extends android.database.sqlite.SQLiteOpenHelper{
	private final static int DATABASE_VERSION = 2; 
	public DataBaseOpenHelper(Context context) {
		this(context, "dview242.db", null,DATABASE_VERSION);	
	}
	/**
	 * 
	 * @param context
	 * @param name       
	 */
	public DataBaseOpenHelper(Context context, String name) {
		this(context, name, null,DATABASE_VERSION);	
	}
	
	public DataBaseOpenHelper(Context context, String name, CursorFactory factory) {
		this(context, name, factory,DATABASE_VERSION);	
	}
	public DataBaseOpenHelper(Context context, String name, CursorFactory factory,int version){
		super(context, name, factory,version);
	}
	
	//  table 
	@Override
	public void onCreate(SQLiteDatabase db) { 
		//decimal(19,0),sqlite     date     (    ),    decimal(19,0)     ;
		String userSql="create table user(_id decimal(19,0) primary key,State decimal(19,0),Uid text,Login_Name text,UserInfo text,Password text,Real_Name text,rememberMe integer,autoLogin integer)";
		db.execSQL(userSql); 

	} 
	
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
		String s="DROP TABLE IF EXISTS ";
		String userSql=s+"user";	

		
		db.execSQL(userSql);
		onCreate(db); 
	} 
	 
	@Override
	public synchronized void close() {
		super.close();
	} 
}

次に、この接続を単一の例で管理し、同じ時間に1つの接続しかなく、1つの読み取りまたは書き込みの操作しかないことを保証します.
public class DataBaseManager {
	private static DataBaseManager instance;
    @SuppressWarnings("unused")
	private static DataBaseOpenHelper databaseHelper;
    private AtomicInteger mOpenCounter = new AtomicInteger();

    @SuppressLint("NewApi")
	public static synchronized void initializeInstance(Context c) {
        if (instance == null) {
            instance = new DataBaseManager();
            databaseHelper =new DataBaseOpenHelper(c);
            if(Build.VERSION.SDK_INT>17)
            { 
            	databaseHelper.setWriteAheadLoggingEnabled(true);
            }
        }
    }

    public static synchronized DataBaseManager getInstance() {
        if (instance == null) {
            throw new IllegalStateException(DataBaseManager.class.getSimpleName() +
                    " is not initialized, call initializeInstance(..) method first.");
        }
        return instance;
    }

    public synchronized SQLiteDatabase openDatabase() {
        if(mOpenCounter.incrementAndGet() == 1) {
            return  databaseHelper.getWritableDatabase();
        }
        return null;
    }

    public synchronized void closeDatabase() {
        if(mOpenCounter.decrementAndGet() == 0) {
        	databaseHelper.close();
        }
    }  
       
}

3.使用方法:
最初に起動したactivityまたはアプリケーションでdbManagerを呼び出す.initializeInstance(getApplicationContext());一度初期化すればいい.
その後、DataBaseManager getInstance()を呼び出してDataBaseManagerインスタンスを取得し、
つまり、トランザクションを開く必要がなく、読み取り操作を制御層で使用できます.しかし、書き込み操作は、トランザクションのオンとオフを覚えておく必要があります.
 public LoginType getLoginType(){
    	   LoginType lt=new LoginType();
    	   lt.setId(1L);
    	 SQLiteDatabase db = null;
    	   try {
    		   db=baseDao.openDataBase();
    		   lt=baseDao.get(db, lt);
			   return lt;
		} catch (Exception e) {
			return null;
		}finally{
			baseDao.closeDataBase();
		}
       }
       
       public boolean saveOrUpdate(LoginType loginType){
    	   if(loginType==null||loginType.getId()==null)
    		   return false;
    	   SQLiteDatabase db = null;
    	   try {
    		   db=baseDao.openDataBase();
    		   db.beginTransaction();
    		   baseDao.saveOrUpdate(db, loginType);
    		   db.setTransactionSuccessful();
			   return true;
		} catch (Exception e) {
			return false;
		}finally{
			if(db!=null)
			db.endTransaction();
			baseDao.closeDataBase();
		}
    	   
       }

注意:
baseDaoのopenとcloseで呼び出されたDataBaseManagerのopenとclose.
まだ失敗またはdatabase is lockedエラーが発生している場合は、データベースの開いた回数と閉じた回数が一致しているかどうかを確認します(つまり、データベースを閉じるのを忘れたかどうかを確認します).
トランザクション(すなわち、db.s e t t T r a n s actionSuccessful()とdbを閉じるのを忘れたかどうかを確認します.endTransaction()メソッド