Transacción de base de datos de Android

84

He creado una base de datos. Quiero hacer la transacción. SaveCustomer()contiene más de una instrucción para insertar registros en la Customer, CustomerControl, Profile, Paymenttabla en ese momento.

Cuando un usuario llama al SaveCustomer()método, esos datos irán a estas 4 tablas. Entonces, ¿cómo puedo hacer la transacción? Si las inserciones de una tabla fallaron, es necesario revertir todo. Por ejemplo, cuando la tercera tabla inserta el registro, obtengo un error, entonces también necesito revertir los registros de inserción de 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);

}

Asimismo, otra declaración también existe.

El código de 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;
       }

}

problema de bloqueo de la base de datos en HTC Desire .

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

por favor, ayúdame

Gracias.

Miré esta misma pregunta relacionada:

Kartheepan
fuente

Respuestas:

279

En realidad lo estás haciendo mal. Debe establecer 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

Tienes dos mesas

  1. UNA
  2. segundo

Ahora desea insertar datos en estas dos tablas, pero tendrá que revertir la transacción si obtiene algún error al momento de insertar datos en las tablas.

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

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

  1. Si desea iniciar la transacción, existe un método beginTransaction()
  2. Si desea confirmar la transacción, hay un método setTransactionSuccessful()que confirmará los valores en la base de datos
  3. Si había iniciado la transacción, debe cerrar la transacción para que haya un método endTransaction()que termine la transacción de su base de datos.

Ahora hay dos puntos principales

  1. Si desea transacción exitosa conjunto que necesita para escribir setTransactionSuccessful()y luego endTransaction()después debeginTransaction()
  2. Si desea revertir su transacción, debe hacerlo endTransaction()sin comprometer la transacción por setTransactionSuccessful().

Puede obtener información detallada sobre la transacción de la base de datos SQLite desde aquí

En tu caso

Puede llamar a su saveCustomer()función en try and catch blocks

db.beginTransaction();
try {
    saveCustomer();
    db.setTransactionSuccessful();
} catch {
    //Error in between database transaction 
} finally {
    db.endTransaction();
}
Dharmendra
fuente
11
Debería agregar endTransactionsu bloque finalmente, no su bloque de prueba.
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
25

debe agregar endTransactionen su finally, no en su bloque de prueba

 finally {
     myDataBase.endTransaction();
   }

Los cambios se revertirán si alguna transacción finaliza sin estar marcada como limpia (llamando a setTransactionSuccessful). De lo contrario, se comprometerán.

Labeeb Panampullan
fuente
1
Gracias por la información. En mi 'SaveCustomer () `voy a llamar' long n = dbAdapter.insertRecordsInDB (" Customer ", null, initialValues); ' en 4 tiempos con diferentes registros. Revertirá todo, si se produce algún error incluso en la tabla del medio. Tengo 4 tablas. ¿Necesito agregar registros en 4 tablas con registros diferentes?
Kartheepan
17

Insertar registro usando 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();
Piyush
fuente