Android-Datenbanktransaktion

84

Ich habe eine Datenbank erstellt. Ich möchte die Transaktion durchführen. SaveCustomer()enthält mehr als eine Anweisung zum Einfügen von Datensätzen in die Customer, CustomerControl, Profile, PaymentTabelle zu diesem Zeitpunkt.

Wenn ein Benutzer die SaveCustomer()Methode aufruft, werden diese Daten in diese 4 Tabellen verschoben. Wie kann ich die Transaktion durchführen? Wenn das Einfügen einer Tabelle fehlgeschlagen ist, muss alles zurückgesetzt werden. Wenn beispielsweise die dritte Tabelle den Datensatz einfügt, ist eine Fehlermeldung aufgetreten, und die Einfügungsdatensätze der beiden vorherigen Tabellen müssen ebenfalls zurückgesetzt werden.

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

}

Ebenso andere Aussage auch dort.

Der DBAdpter-Code lautet:

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

Dies ist der vollständige Code:

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

}

Problem mit der Datenbanksperre in HTC Desire .

Ich möchte ein Rollback durchführen, wenn beim Einfügen der Tabellendaten Probleme aufgetreten sind.

Bitte hilf mir

Vielen Dank.

Ich sah die gleiche verwandte Frage:

Kartheepan
quelle

Antworten:

279

Eigentlich machst du falsch. Sie müssen die Starttransaktion festlegen, wenn Sie mehrere Datensätze in die Datenbank einfügen möchten oder wenn Sie Daten aus einer anderen Tabelle zurücksetzen müssen, wenn beim Einfügen von Daten in eine der Datenbanktabellen ein Problem auftritt.

Beispielsweise

Sie haben zwei Tabellen

  1. EIN
  2. B.

Jetzt möchten Sie Daten in diese beiden Tabellen einfügen, müssen jedoch die Transaktion zurücksetzen, wenn beim Einfügen von Daten in die Tabellen ein Fehler auftritt.

Jetzt haben Sie erfolgreich Daten in Tabelle A eingefügt und versuchen nun, Daten in Tabelle B einzufügen. Wenn Sie zum Zeitpunkt des Einfügens von Daten in Tabelle B einen Fehler erhalten, müssen Sie relevante Daten aus Tabelle A löschen, dh Sie müssen die Transaktion zurücksetzen.

Wie Sie Datenbanktransaktionen in Android verwenden können

  1. Wenn Sie die Transaktion starten möchten, gibt es eine Methode beginTransaction()
  2. Wenn Sie die Transaktion festschreiben möchten, gibt es eine Methode, mit setTransactionSuccessful()der die Werte in der Datenbank festgeschrieben werden
  3. Wenn Sie die Transaktion gestartet haben, müssen Sie die Transaktion schließen, damit es eine Methode gibt, mit endTransaction()der Ihre Datenbanktransaktion beendet wird

Nun gibt es zwei Hauptpunkte

  1. Wenn Sie Satz Transaktion erfolgreich wollen , müssen Sie schreiben setTransactionSuccessful()und dann endTransaction()nachbeginTransaction()
  2. Wenn Sie Ihre Transaktion zurücksetzen möchten, müssen Sie dies tun, endTransaction()ohne die Transaktion von festzuschreiben setTransactionSuccessful().

Detaillierte Informationen zur SQLite-Datenbanktransaktion erhalten Sie hier

In deinem Fall

Sie können Ihre saveCustomer()Funktion in Try-and-Catch-Blöcken aufrufen

db.beginTransaction();
try {
    saveCustomer();
    db.setTransactionSuccessful();
} catch {
    //Error in between database transaction 
} finally {
    db.endTransaction();
}
Dharmendra
quelle
11
Sie sollten endTransactionin Ihrem final, nicht in Ihrem try-Block hinzufügen .
VansFannel
6
@VansFannel Sie haben Recht, endlich ist der beste Ort, um die Datenbanktransaktion zu schließen. Danke, dass du es besser gemacht hast.
Dharmendra
25

Sie sollten endTransactionin Ihrem finally, nicht in Ihrem try-Block hinzufügen

 finally {
     myDataBase.endTransaction();
   }

Die Änderungen werden zurückgesetzt, wenn eine Transaktion beendet wird, ohne als sauber markiert zu werden (durch Aufrufen von setTransactionSuccessful). Andernfalls werden sie verpflichtet.

Labeeb Panampullan
quelle
1
Danke für die Auskunft. In meinem 'SaveCustomer ()' werde ich 'long n = dbAdapter.insertRecordsInDB ("Customer", null, initialValues) aufrufen;' in 4 mal mit verschiedenen aufzeichnungen. Wird alles zurückgesetzt, wenn selbst in der mittleren Tabelle ein Fehler auftritt? Ich habe 4 Tabellen. Müssen Datensätze in 4 Tabellen mit unterschiedlichen Datensätzen hinzugefügt werden?
Kartheepan
17

Datensatz mithilfe der Transaktion einfügen. Dies ist sehr schnell

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
quelle