2012-10-19 14 views
5

मैं एंड्रॉइड पर एसक्यूलाइट डेटाबेस से लिखने और पढ़ने के लिए SQLiteOpenHelper का उपयोग कर रहा हूं। जब उपयोगकर्ता यूआई पर क्लिक करता है तो मैं AsyncTask का उपयोग करके SQLite डेटाबेस से पढ़ता हूं लेकिन सटीक समो पल पर मैं अन्य AsyncTask का उपयोग करके पृष्ठभूमि में डेटाबेस को अद्यतन और लिख रहा हूं।एंड्रॉइड एसक्यूलाइट मल्टीथ्रेड एक्सेस

हर बार मुझे डेटाबेस लॉक अपवाद मिलता है। मैं इसे कैसे ठीक करूं? क्या एक ही समय में कई धागे से एसक्यूलाइट का उपयोग किया जा सकता है?

मैं इसका उपयोग कर रहा हूं: मेरे पास एक डेटाबेस क्लास है जो SQLiteOpenHelper से फैली हुई है। मैं onCreate और onUpgrade तरीकों को लागू किया और हर मैं डेटाबेस से पढ़ रहा हूँ या डेटाबेस के लिए लिख रहा है कि जैसे SQLiteDatabase का उपयोग करें:

SQLiteDatabase database = null; 
try { 

    database = new Database(context).getWritableDatabase(); 

    .... 
    writing and reading from database... 
    .... 

} catch (Exception e) { 
    e.printStackTrace(); 
} finally { 
    if (database != null) { 
     database.close(); 
    } 
} 

अंत मैं भी करीब SQLiteStatements और Cursors पर अगर मैं उन्हें का उपयोग करें। क्या मुझे @ जस्टिन उत्तर का उपयोग करना चाहिए और एप्लिकेशन में डेटाबेस क्लास का सिंगलटन होना चाहिए?

E/SqliteDatabaseCpp(17377): sqlite3_open_v2("/data/data/com.skulptur/databases/LGM.s3db", &handle, 6, NULL) failed 
E/SQLiteDatabase(17377): Failed to open the database. closing it. 
E/SQLiteDatabase(17377):  android.database.sqlite.SQLiteDatabaseLockedException: database is locked 
E/SQLiteDatabase(17377): at android.database.sqlite.SQLiteDatabase.dbopen(Native Method) 
E/SQLiteDatabase(17377): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:983) 
E/SQLiteDatabase(17377): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:956) 
E/SQLiteDatabase(17377): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1021) 
E/SQLiteDatabase(17377): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:750) 
E/SQLiteDatabase(17377): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221) 
E/SQLiteDatabase(17377): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:149) 
E/SQLiteDatabase(17377): at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:223) 
+0

मुझे लगता है कि एसक्यूलाइट पर एंड्रॉइड लाइब्रेरीज़ के साथ आप जो कुछ भी कर सकते हैं वह सिंक्रनाइज़ है। क्या आप अपवाद को आजमा सकते हैं और पकड़ सकते हैं और यदि आपको लॉक स्थिति मिलती है तो पुनः प्रयास करें? – quinestor

+1

क्या आप अपनी पोस्ट संपादित कर सकते हैं और अपवाद की पहली पंक्ति और किसी भी कारण बयान दे सकते हैं? मुझे संदेह है कि आप जो कर रहे हैं उसके बारे में कम है और एक बंद डेटाबेस या कुछ का पुनः उपयोग करने के बारे में अधिक जानकारी है। – Gray

उत्तर

7

यह है कि मैं क्या मुद्दों पर ताला लगा से बचने के लिए .. मैं अपने आवेदन मेरी db सहायक का एक उदाहरण संभालने के लिए और हमेशा यह उल्लेख करने के लिए मेरी डीबी पर एक संभाल पाने के लिए करते हैं करते हैं।

public class MyApp extends Application { 
    // My instance of SQLiteOpenHelper 
    public static DbHelper openHelper; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     if (openHelper == null) { 
      openHelper = new DbHelper(this); 
     } 
    } 

    public synchronized static SQLiteDatabase getDB() { 
     return openHelper.getWritableDatabase(); 
    } 
} 

एक बार जब आप ऐसा करते हैं, किसी भी समय आप एक डाटाबेस क्वेरी करना चाहते हैं, MyApp.getDB तरह db हैंडल() हो जाते हैं और अगर आप अवरोधित मुद्दा है कभी नहीं होगा। हालांकि डीबी को कभी बंद न करें। यह पैटर्न आपके ऐप में हर समय एक कनेक्शन बनाए रखता है।

db.beginTransaction(); 
try { 
    for (DBRow row : insertList) { 
     // your insert code 
     insertRow(row); 
     db.yieldIfContendedSafely(); 
    } 
    db.setTransactionSuccessful(); 
} finally { 
    db.endTransaction(); 
} 

यह अन्य प्रश्नों के लिए खुद को interject करने की अनुमति देगा: SQLite इसलिए यदि आप लंबे समय तक डीबी चल रही प्रक्रियाओं है, एक एकल लेनदेन में एक 1000 आवेषण की तरह आप इस तरह यह कोड करने के लिए चाहता हूँ एंड्रॉयड पर तुल्यकालिक करने के लिए है ताकि आप पृष्ठभूमि ऐप के दौरान अपने ऐप को रोक नहीं पाएंगे।

+2

आप 'अनुप्रयोग' वर्ग को ओवरराइड करने से बेहतर 'SQLiteOpenHelper' एक सिंगलटन बेहतर बना सकते हैं। – kdehairy

+0

हां, मुझे एहसास हुआ कि यह लिखने के बाद: - \ .. मेरा जवाब बदलने की तरह महसूस नहीं हुआ – JustinMorris

+6

मुझे डर है कि आप लॉकिंग समस्या कभी नहीं होने की अपनी धारणा के बारे में गलत हैं: केवल एक चीज जिसे आप सिंक्रनाइज़ कर रहे हैं वह आपकी पहुंच है 'getWritableDatabase' विधि के लिए, जिसका अर्थ है: केवल * यह * कभी भी एक साथ नहीं बुलाया जाएगा, 'SQLiteDatabase' ऑब्जेक्ट के साथ कभी भी क्या होता है, यह * सिंक्रनाइज़ नहीं होता है *। – theV0ID

1

वहाँ कुछ चीजें कोशिश करने के लिए कर रहे हैं:

यह त्रुटि मैं हो रही है। सबसे पहले अपने प्रत्येक कार्य में SQLiteOpenHelper के समान उदाहरण को पारित करने का प्रयास करें। दूसरा आपके हेल्पर के अंदर अपने SQLiteDatabase पर StartTransaction और EndTransaction का उपयोग कर रहा है। तीसरा synchronized जोड़ रहा है जो आपके प्रत्येक सहायक मेथेंड कार्यों में उपयोग किया जा रहा है।

+0

आपका रास्ता ठीक है, लेकिन मैं ContentProvider पसंद करता हूं, यह मुझे ऐप और डीबी के बीच अलगाव देता है। आप ORMLite या किसी अन्य ORM- जैसी lib पर भी विचार कर सकते हैं, उनमें से कई हैं, अच्छा उदाहरण है जो मैंने कुछ समय पहले किया था https: // github।com/rysiekblah/crom –

0

मुझे लगता है कि आप डेटाबेस कनेक्शन का गलत इस्तेमाल कर रहे हैं। यह अनजान कर्सर या अन्यथा के कारण हो सकता है। स्क्लाइट डेटाबेस कार्यान्वयन थ्रेड सुरक्षित है और विभिन्न धागे से एक साथ उपयोग किया जा सकता है। कृपया अपनी समस्या के बारे में अधिक जानकारी प्रदान करें (अपवाद स्टैक ट्रेस, कोड नमूना जो अपवाद आदि का कारण बनता है) ताकि हम आपकी मदद कर सकें।

संबंधित मुद्दे