Transaction de base de données Android

84

J'ai créé une base de données. Je veux faire la transaction. SaveCustomer()contient plus d'une instruction pour insérer des enregistrements dans la Customer, CustomerControl, Profile, Paymenttable à ce moment.

Lorsqu'un utilisateur appelle la SaveCustomer()méthode, ces données iront à ces 4 tables. Comment puis-je effectuer la transaction? Si une insertion de table échoue, vous devez tout annuler. Par exemple, lorsque la troisième table insère l'enregistrement, j'ai une erreur, puis je dois également annuler les enregistrements d'insertion des deux tables précédentes.

Voir mon code:

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

}

De même autre déclaration également là.

Le code DBAdpter est:

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

Voici le code complet:

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

}

problème de verrouillage de base de données dans HTC Desire .

Je souhaite revenir en arrière en cas de problème lors de l'insertion des données de la table.

Aidez-moi, s'il vous plaît

Merci.

J'ai regardé cette même question connexe:

Kartheepan
la source

Réponses:

279

En fait, vous vous trompez. Vous devez définir begin transaction si vous avez plusieurs enregistrements à insérer dans la base de données ou si vous devez restaurer des données d'une autre table en cas de problème lors de l'insertion de données dans l'une des tables de la base de données.

Par exemple

Vous avez deux tables

  1. UNE
  2. B

Vous souhaitez maintenant insérer des données dans ces deux tables, mais vous devrez annuler la transaction si vous rencontrez une erreur au moment de l'insertion des données dans les tables.

Maintenant, vous avez réussi à insérer des données dans le tableau A et maintenant vous essayez d'insérer des données dans le tableau B.Maintenant, si vous obtenez une erreur au moment de l'insertion des données dans le tableau B, vous devez supprimer les données pertinentes du tableau A, ce qui signifie que vous doivent annuler la transaction.

Comment utiliser la transaction de base de données sous Android

  1. Si vous souhaitez démarrer la transaction, il existe une méthode beginTransaction()
  2. Si vous souhaitez valider la transaction, il existe une méthode setTransactionSuccessful()qui validera les valeurs dans la base de données
  3. Si vous aviez commencé la transaction, vous devez fermer la transaction afin qu'il existe une méthode endTransaction()qui mettra fin à votre transaction de base de données

Maintenant, il y a deux points principaux

  1. Si vous souhaitez que la transaction soit réussie, vous devez écrire setTransactionSuccessful(), puis endTransaction()aprèsbeginTransaction()
  2. Si vous souhaitez annuler votre transaction, vous devez le faire endTransaction()sans valider la transaction par setTransactionSuccessful().

Vous pouvez obtenir des informations détaillées sur la transaction de base de données SQLite à partir d' ici

Dans ton cas

Vous pouvez appeler votre saveCustomer()fonction dans les blocs try and catch

db.beginTransaction();
try {
    saveCustomer();
    db.setTransactionSuccessful();
} catch {
    //Error in between database transaction 
} finally {
    db.endTransaction();
}
Dharmendra
la source
11
Vous devez ajouter endTransactionvotre bloc Enfin, pas dans votre bloc try.
VansFannel
6
@VansFannel vous avez raison est enfin le meilleur endroit pour clôturer la transaction de base de données. merci de l'améliorer.
Dharmendra
25

vous devez ajouter endTransactionvotre finally, pas votre bloc d'essai

 finally {
     myDataBase.endTransaction();
   }

Les modifications seront annulées si une transaction est terminée sans être marquée comme propre (en appelant setTransactionSuccessful). Sinon, ils seront engagés.

Labeeb Panampullan
la source
1
Merci pour l'information. Dans mon 'SaveCustomer () `je vais appeler' long n = dbAdapter.insertRecordsInDB (" Customer ", null, initialValues); ' en 4 temps avec différents enregistrements. Va-t-il tout annuler, s'il y a des erreurs même dans la table du milieu.J'ai 4 table.Besoin d'ajouter des enregistrements dans 4 tables avec des enregistrements différents.?
Kartheepan
17

Insérer un enregistrement à l'aide d'une transaction, c'est très rapide

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
la source