2014-11-04 4 views
1

싱글 톤 패턴으로 SQliteOpenHelper를 구현했으며 지금까지는 제대로 작동합니다. 조각이 업데이트 기록에 트랜잭션을 시작데이터 서비스와 싱글 톤 SQliteOpenHelper

  • 서비스는
  • 트랜잭션이 어떤 이유로 실패 업데이트 된 데이터를 읽 트리거됩니다 및

롤백됩니다

  • :하지만 아래의 순서를 고려 서비스는 나중에 롤백 된 커밋되지 않은 데이터를 처리했을 것입니다. 따라서 서비스와 결합 된 싱글 톤 패턴이 데이터 격리에 문제를 일으키는 것으로 보입니다. 그러나 나는 싱글 톤을 추천하는 수많은 게시물을 읽었습니다. 싱글 톤을 사용할 때이 시나리오를 어떻게 처리합니까? 트랜잭션

    public class MyApplication extends Application{ 
        private static MyApplication instance; 
        public MyApplication(){ 
         instance = this; 
        } 
        public static Context getContext(){ 
         return instance; 
        } 
    } 
    
    public class LocalDBHelper extends SQLiteOpenHelper{ 
        private static final int DATABASE_VERSION = 1; 
        private static final String DATABASE_NAME = "MyDB"; 
        private static final String LOG_TAG = "LocalDBHelper"; 
    
        private static LocalDBHelper instance = null; 
        /*private constructor to avoid direct instantiation by other classes*/ 
        private LocalDBHelper(){ 
         super(MyApplication.getContext(), DATABASE_NAME, null, DATABASE_VERSION); 
        } 
        /*synchronized method to ensure only 1 instance of LocalDBHelper exists*/ 
        public static synchronized LocalDBHelper getInstance(){ 
         if(instance == null){ 
          instance = new LocalDBHelper(); 
         } 
         return instance; 
        } 
        ... 
        ... 
    } 
    

    사용법 :

    SQLiteDatabase db = LocalDBHelper.getInstance().getWritableDatabase(); 
    db.beginTransaction(); 
    try{ 
    .... 
    ... 
    db.setTransactionSuccessful(); 
    }catch(Exception e){ 
        e.printStackTrace(); 
    } 
    finally{ 
        db.endTransaction(); 
    } 
    
  • +0

    이 내용을 확인해야합니다. http://blog.lemberg.co.uk/concurrent-database-access –

    +0

    @ user2247689 감사합니다. 나는 3 개의 다른 사이트에서 같은 기사를 읽었습니다. :) 그러나 트랜잭션이나 격리, 그래서 질문에 무관하다. – faizal

    +0

    죄송합니다. 질문을 제대로 읽지 않았습니다. 특히 서비스를 병행해야 할 때 서비스 다루는 일은 다소 까다 롭습니다. 기본적으로 '메시지'를 사용해야 할 것 같습니까? 이 http://developer.android.com/guide/components/bound-services.html#Messenger –

    답변

    2
    1. 서비스는 주 스레드에서 실행됩니다. 자체 스레드가 없습니다. 주 스레드가 작업을 마친 후에 만 ​​실행됩니다. 따라서 트랜잭션이 활동/조각에서 실행될 때 서비스가 시작될 위험이 없습니다.

    2. 두 개의 스레드가 동일한 SQliteDatabase 연결에 액세스 할 수 없습니다. 시스템은 모든 스레드가 풀에서 고유 한 연결에 액세스 할 수 있도록 설계되었습니다. 사용 가능한 연결이 없으면 다른 스레드는 하나를 대기합니다. 충분히 오래 기다려야한다면 아래 전화에서 볼 수있는 것과 비슷한 logcat 경고가 표시됩니다. 따라서 싱글 톤 패턴은 SQLite의 스레드 안전성을 보완합니다. # 2의 결과로서

    3. W/SQLiteConnectionPool(12695): The connection pool for database 'xyz' has been unable to grant a connection to thread 6386 (AsyncTask #2) with flags 0x1 for 4.0 seconds. W/SQLiteConnectionPool(12695): Connections: 0 active, 1 idle, 0 available.

      , 당신은 싱글 톤을 사용하는 경우 다른 스레드에 의해 커밋되지 않은 데이터를 읽을 할 수있는 방법이 없습니다. 싱글 톤을 사용하지 않더라도 기본적으로 SQLite는 연결간에 데이터 분리를 제공합니다. https://www.sqlite.org/isolation.html을 참조하십시오.

    결론 : 동일한 스레드에서 트랜잭션이 종료되기 전에 경우 싱글로 커밋되지 않은 데이터를 읽을 수있는 유일한 방법입니다.

    +1

    미리 쓰기 로깅이 활성화되지 않은 경우 연결 풀이 최대 1로 설정되어 있지만 실제로는 필요하지 않으며 나중에 변경 될 수 있습니다. 그러나 각 스레드는 다른 세션을 사용하고 풀에서 고유 한 연결을 확보합니다. 물론 SQLite는 여전히 자체 잠금 및 동시성 모델을 구현합니다. thanks @ corsair992. – corsair992

    +0

    .SQLiteDatabase 인스턴스와 연결 인스턴스를 혼동했습니다. 나는 귀하의 의견을 반영하기 위해 # 2를 편집했습니다. – faizal

    관련 문제