2011-11-16 10 views
71

He creado una base de datos. Quiero hacer la Transacción SaveCustomer() contiene más de una instrucción para insertar registros en la tabla Customer, CustomerControl, Profile, Payment en ese momento.Android Database Transaction

Cuando un usuario llama al método SaveCustomer(), esa información irá a estas 4 tablas.so ¿Cómo puedo hacer la transacción? Si una tabla insertada falla, entonces necesita deshacer todo. Por ejemplo, cuando la tercera tabla inserta el registro, recibí un error, luego también tuve que revertir los registros de inserción de las dos tablas anteriores.

Ver mi código:

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); 

} 

Del mismo modo otra declaración también allí.

código DBAdpter es:

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; 
} 

Este es el código completo:

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.

Quiero retroceder si ocurriera algún problema al insertar los datos de la tabla.

Por favor, ayúdenme

Gracias.

miré esta misma pregunta relacionada:

Respuesta

24

se debe añadir endTransaction en su finally, no en el bloque try

finally { 
    myDataBase.endTransaction(); 
    } 

Los cambios se pueden revertir si alguna transacción se terminó sin marcado como limpio (llamando a setTransactionSuccessful). De lo contrario, se cometerán.

+1

Gracias por la información. En mi 'SaveCustomer() 'voy a llamar' long n = dbAdapter.insertRecordsInDB (" Customer ", null, initialValues); ' en 4 veces con diferentes registros. ¿Revertirá todo, si hay algún error, incluso en la mesa del medio. Tengo 4 tablas. Necesito agregar registros en la tabla 4 con registros diferentes. – Kartheepan

258

En realidad lo estás haciendo mal. Debe iniciar la transacción de inicio si tiene varios registros para insertar en la base de datos o si tiene que deshacer los datos de otra tabla si hay un problema al insertar datos en una de las tablas de la base de datos.

Por ejemplo

tiene dos tablas

  1. Un
  2. B

Ahora que desea insertar los datos en estas dos tablas, sino que tendrá que deshacer la transacción si obtendrá cualquier error al momento de insertar datos en las tablas.

Ahora ha insertado con éxito los datos en la tabla A y ahora está tratando de insertar datos en la tabla B. Ahora si obtiene un error en el momento de insertar los datos en la tabla B, debe eliminar los datos relevantes de la tabla A eso significa que debe deshacer la transacción.

¿Cómo se puede utilizar la transacción de base de datos en Android

  1. Si desea iniciar la transacción no es un método beginTransaction()
  2. Si desea confirmar la transacción no es un método setTransactionSuccessful() que se comprometan los valores en la base de datos
  3. Si tuvo que iniciar la transacción, debe cerrar la transacción para que haya un método endTransaction() que finalizará su transacción de base de datos

Ahora hay dos puntos principales

  1. Si desea establecer transacción exitosa es necesario escribir setTransactionSuccessful() y luego endTransaction() después beginTransaction()
  2. Si desea deshacer la transacción entonces necesita endTransaction() sin confirmando la transacción por setTransactionSuccessful().

Puede obtener información detallada acerca de la transacción de base de datos SQLite desde here

En su caso

Puede llamar a su función saveCustomer() en bloques try y catch

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

Gracias por esta información. ¡Es más útil para mí! Gracias de nuevo – Piraba

+11

Debe agregar 'endTransaction' en su finalmente, no en su bloque try. – VansFannel

+6

@VansFannel tiene razón, finalmente es el mejor lugar para cerrar la transacción de la base de datos. gracias por hacerlo mejor. – Dharmendra

11

Insertar Registro usando la transacción, esto es muy rápido

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();