2011-11-16 13 views
71

Utworzyłem bazę danych. Chcę wykonać transakcję. SaveCustomer() zawiera więcej niż jedną instrukcję do wstawiania rekordów do tabeli Customer, CustomerControl, Profile, Payment w tym czasie.Android Database Transaction

Gdy użytkownik zadzwoni pod numer SaveCustomer(), wówczas dane te zostaną przesłane do tych 4 tabel. W jaki sposób mogę wykonać transakcję? Jeśli jedna tabela wstawi się nie powiodło się, to trzeba cofnąć wszystko. Na przykład, gdy trzecia tabela wstawi rekord, otrzymam błąd, a następnie trzeba cofnąć poprzednie rekordy wstawiania dwóch tabel również.

Zobacz mój kod:

public void saveCustomer(){ 
    DBAdapter dbAdapter = DBAdapter.getDBAdapterInstance(RetailerOrderKeyActivity.this); 
    dbAdapter.openDataBase(); 
    ContentValues initialValues = new ContentValues(); 
    initialValues.put("CustomerName",customer.getName()); 
    initialValues.put("Address",customer.getAddress()); 
    initialValues.put("CustomerPID",strPID); 
    initialValues.put("Date",strDateOnly); 
    long n = dbAdapter.insertRecordsInDB("Customer", null, initialValues); 

} 

Podobnie inne oświadczenie również tam.

kod DBAdpter jest:

public long insertRecordsInDB(String tableName, String nullColumnHack,ContentValues initialValues) { 
    long n =-1; 
    try { 
     myDataBase.beginTransaction(); 
     n = myDataBase.insert(tableName, nullColumnHack, initialValues); 

     myDataBase.endTransaction(); 
     myDataBase.setTransactionSuccessful(); 
    } catch (Exception e) { 
     // how to do the rollback 
     e.printStackTrace(); 
    } 

    return n; 
} 

Jest to pełny kod:

public class DBAdapter extends SQLiteOpenHelper { 

    private static String DB_PATH = "/data/data/com.my.controller/databases/"; 
    private static final String DB_NAME = "customer"; 
    private SQLiteDatabase myDataBase; 
    private final Context myContext; 
    private static DBAdapter mDBConnection; 


    private DBAdapter(Context context) { 
     super(context, DB_NAME, null, 1); 
     this.myContext = context; 
     DB_PATH = "/data/data/" 
       + context.getApplicationContext().getPackageName() 
       + "/databases/"; 
     // The Android's default system path of your application database is 
     // "/data/data/mypackagename/databases/" 
    } 


    public static synchronized DBAdapter getDBAdapterInstance(Context context) { 
     if (mDBConnection == null) { 
      mDBConnection = new DBAdapter(context); 
     } 
     return mDBConnection; 
    } 


    public void createDataBase() throws IOException { 
     boolean dbExist = checkDataBase(); 
     if (dbExist) { 
      // do nothing - database already exist 
     } else { 
      // By calling following method 
      // 1) an empty database will be created into the default system path of your application 
      // 2) than we overwrite that database with our database. 
      this.getReadableDatabase(); 
      try { 
       copyDataBase(); 
      } catch (IOException e) { 
       throw new Error("Error copying database"); 
      } 
     } 
    } 


    private boolean checkDataBase() { 
     SQLiteDatabase checkDB = null; 

     try { 
      String myPath = DB_PATH + DB_NAME; 
      checkDB = SQLiteDatabase.openDatabase(myPath, null,SQLiteDatabase.OPEN_READONLY); 

     } catch (SQLiteException e) { 
      // database does't exist yet. 
     } 
     if (checkDB != null) { 
      checkDB.close(); 
     } 
     return checkDB != null ? true : false; 
    } 


    private void copyDataBase() throws IOException { 
     InputStream myInput = myContext.getAssets().open(DB_NAME); 
     String outFileName = DB_PATH + DB_NAME; 
     OutputStream myOutput = new FileOutputStream(outFileName); 
    byte[] buffer = new byte[1024]; 
     int length; 
     while ((length = myInput.read(buffer)) > 0) { 
      myOutput.write(buffer, 0, length); 
     } 
      // Close the streams 
     myOutput.flush(); 
     myOutput.close(); 
     myInput.close(); 
    } 

    /** 
    * Open the database 
    * @throws SQLException 
    */ 
    public void openDataBase() throws SQLException { 
     String myPath = DB_PATH + DB_NAME; 
     myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);  
    } 


    @Override 
    public synchronized void close() { 
     if (myDataBase != null) 
      myDataBase.close(); 
     super.close(); 
    } 

    /** 
    * Call on creating data base for example for creating tables at run time 
    */ 
    @Override 
    public void onCreate(SQLiteDatabase db) { 
    } 


    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     db.execSQL("ALTER TABLE WMPalmUploadControl ADD Testing int"); 

    } 

    public void upgradeDb(){ 
     onUpgrade(myDataBase, 1, 2); 
    } 

    public Cursor selectRecordsFromDB(String tableName, String[] tableColumns, 
      String whereClase, String whereArgs[], String groupBy, 
      String having, String orderBy) { 
     return myDataBase.query(tableName, tableColumns, whereClase, whereArgs, 
       groupBy, having, orderBy); 
    } 


    public ArrayList<ArrayList<String>> selectRecordsFromDBList(String tableName, String[] tableColumns, 
      String whereClase, String whereArgs[], String groupBy, 
      String having, String orderBy) {   

     ArrayList<ArrayList<String>> retList = new ArrayList<ArrayList<String>>(); 
      ArrayList<String> list = new ArrayList<String>(); 
      Cursor cursor = myDataBase.query(tableName, tableColumns, whereClase, whereArgs, 
        groupBy, having, orderBy);   
      if (cursor.moveToFirst()) { 
      do { 
       list = new ArrayList<String>(); 
       for(int i=0; i<cursor.getColumnCount(); i++){     
        list.add(cursor.getString(i)); 
       } 
       retList.add(list); 
      } while (cursor.moveToNext()); 
      } 
      if (cursor != null && !cursor.isClosed()) { 
      cursor.close(); 
      } 
      return retList; 

    } 


    public long insertRecordsInDB(String tableName, String nullColumnHack,ContentValues initialValues) { 
     long n =-1; 
     try { 
      myDataBase.beginTransaction(); 
      n = myDataBase.insert(tableName, nullColumnHack, initialValues); 

      myDataBase.endTransaction(); 
      myDataBase.setTransactionSuccessful(); 
     } catch (Exception e) { 
      // how to do the rollback 
      e.printStackTrace(); 
     } 

     return n; 
    } 


    public boolean updateRecordInDB(String tableName, 
      ContentValues initialValues, String whereClause, String whereArgs[]) { 
     return myDataBase.update(tableName, initialValues, whereClause, 
       whereArgs) > 0;    
    } 

    public int updateRecordsInDB(String tableName, 
      ContentValues initialValues, String whereClause, String whereArgs[]) { 
     return myDataBase.update(tableName, initialValues, whereClause, whereArgs);  
    } 


    public int deleteRecordInDB(String tableName, String whereClause, 
      String[] whereArgs) { 
     return myDataBase.delete(tableName, whereClause, whereArgs); 
    } 


    public Cursor selectRecordsFromDB(String query, String[] selectionArgs) { 
     return myDataBase.rawQuery(query, selectionArgs);  
    } 


    public ArrayList<ArrayList<String>> selectRecordsFromDBList(String query, String[] selectionArgs) {  
      ArrayList<ArrayList<String>> retList = new ArrayList<ArrayList<String>>(); 
      ArrayList<String> list = new ArrayList<String>(); 
      Cursor cursor = myDataBase.rawQuery(query, selectionArgs);    
      if (cursor.moveToFirst()) { 
      do { 
       list = new ArrayList<String>(); 
       for(int i=0; i<cursor.getColumnCount(); i++){     
        list.add(cursor.getString(i)); 
       } 
       retList.add(list); 
      } while (cursor.moveToNext()); 
      } 
      if (cursor != null && !cursor.isClosed()) { 
      cursor.close(); 
      } 
      return retList; 
     } 

} 

database lock issue in HTC Desire.

Chcę wycofać, jeśli wystąpiły problemy podczas wstawiania danych tabeli.

Proszę mi pomóc

Dzięki.

Spojrzałem tę samą powiązane pytanie:

Odpowiedz

24

należy dodać endTransaction w swojej finally, a nie w bloku try

finally { 
    myDataBase.endTransaction(); 
    } 

Zmiany zostaną cofnięte, jeżeli każda transakcja jest zakończona bez oznaczane jako czyste (przez wywołanie metody setTransactionSupcessful). W przeciwnym razie zostaną popełnione.

+1

Dzięki za informację. W moim 'SaveCustomer() 'mam zamiar wywołać' long n = dbAdapter.insertRecordsInDB (" Klient ", null, initialValues); ' w 4 czasie z różnymi rekordami. Czy przywróci wszystko, jeśli wystąpi erro nawet w środkowym stoliku. Mam 4 table.Need, aby dodać rekordy w 4 tabeli z różnymi rekordami.? – Kartheepan

258

W rzeczywistości robisz źle. Musisz ustawić rozpocznij transakcję, jeśli masz wiele rekordów do wstawienia do bazy danych lub , jeśli musisz wycofać dane z innej tabeli, jeśli wystąpił problem z wstawieniem danych do jednej z tabel bazy danych.

Na przykład

Masz dwie tabele

  1. B

Teraz chcesz wstawić dane w tych dwóch tabelach, ale trzeba będzie wycofać transakcję jeśli ciebie otrzyma błąd w momencie wstawiania danych do tabel.

Teraz pomyślnie wstawiono dane do tabeli A, a teraz próbujesz wstawić dane do tabeli B. Teraz, jeśli pojawi się błąd w momencie wstawiania danych do tabeli B, musisz usunąć odpowiednie dane z tabeli A to oznacza, że ​​musisz wycofać transakcję.

Jak można używać transakcji bazy danych w Android

  1. Jeśli chcesz rozpocząć transakcję istnieje metoda beginTransaction()
  2. Jeśli chcesz popełnić transakcji istnieje metoda setTransactionSuccessful() który popełni wartości w bazie danych
  3. Po rozpoczęciu transakcji należy zamknąć transakcję, aby dostępna była metoda endTransaction(), która zakończy transakcję bazy danych

Obecnie istnieją dwa główne punkty

  1. Jeśli chcesz ustawić transakcję sukces trzeba napisać setTransactionSuccessful() a następnie endTransaction() po beginTransaction()
  2. Jeśli chcesz wycofać transakcję wtedy trzeba endTransaction() bez dokonanie transakcji przez setTransactionSuccessful().

można uzyskać szczegółowe informacje o transakcji bazy danych SQLite od here

W twoim przypadku

można nazwać czynność saveCustomer() w try i catch bloki

db.beginTransaction(); 
try { 
    saveCustomer(); 
    db.setTransactionSuccessful(); 
} catch { 
    //Error in between database transaction 
} finally { 
    db.endTransaction(); 
} 
+3

Dzięki za te informacje. Jest dla mnie bardziej pomocna !!!. Jeszcze raz dziękuję – Piraba

+11

Powinieneś dodać 'endTransaction' w swoim końcu, nie w swoim bloku try. – VansFannel

+6

@VansFannel masz rację w końcu jest najlepszym miejscem do zamknięcia transakcji bazy danych. dzięki za uczynienie tego lepszym. – Dharmendra

11

Insert Rekord przy użyciu transakcji, jest bardzo szybki

String sql = "INSERT INTO table (col1, col2) VALUES (?, ?)"; 
db.beginTransaction(); 

SQLiteStatement stmt = db.compileStatement(sql); 
for (int i = 0; i < values.size(); i++) { 
    stmt.bindString(1, values.get(i).col1); 
    stmt.bindString(2, values.get(i).col2); 
    stmt.execute(); 
    stmt.clearBindings(); 
} 

db.setTransactionSuccessful(); 
db.endTransaction(); 
Powiązane problemy