Транзакция базы данных Android

84

Я создал базу данных. Я хочу совершить транзакцию. SaveCustomer()содержит более одного оператора для вставки записей в Customer, CustomerControl, Profile, Paymentтаблицу в то время.

Когда пользователь вызывает SaveCustomer()метод, эти данные поступают в эти 4 таблицы. Итак, как я могу выполнить транзакцию? Если вставка одной таблицы не удалась, нужно все откатить. Например, когда третья таблица вставляет запись, я получил ошибку, тогда мне также нужно откатить предыдущие две записи вставки таблицы.

Смотрите мой код:

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

}

Там же и другое заявление.

Код DBAdpter:

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

}

проблема с блокировкой базы данных в HTC Desire .

Я хочу выполнить откат, если при вставке данных таблицы возникнут какие-либо проблемы.

пожалуйста, помогите мне

Благодарю.

Я посмотрел на тот же связанный вопрос:

Kartheepan
источник

Ответы:

279

На самом деле вы делаете не так. Вы должны установить начальную транзакцию, если у вас есть несколько записей для вставки в базу данных или если вам нужно откатить данные из другой таблицы, если есть проблема при вставке данных в одну из таблиц базы данных.

Например

У вас есть две таблицы

  1. А
  2. B

Теперь вы хотите вставить данные в эти две таблицы, но вам придется откатить транзакцию, если вы получите какую-либо ошибку во время вставки данных в таблицы.

Теперь вы успешно вставили данные в таблицу A, и теперь вы пытаетесь вставить данные в таблицу B. Теперь, если вы получаете сообщение об ошибке во время вставки данных в таблицу B, вам необходимо удалить соответствующие данные из таблицы A, что означает, что вы придется откатить транзакцию.

Как вы можете использовать транзакцию базы данных в Android

  1. Если вы хотите начать транзакцию, есть способ beginTransaction()
  2. Если вы хотите зафиксировать транзакцию, существует метод, setTransactionSuccessful()который зафиксирует значения в базе данных.
  3. Если вы начали транзакцию, вам нужно закрыть транзакцию, поэтому существует метод, endTransaction()который завершит транзакцию вашей базы данных.

Теперь есть два основных момента

  1. Если вы хотите, чтобы транзакция прошла успешно, вам нужно написать, setTransactionSuccessful()а затем endTransaction()послеbeginTransaction()
  2. Если вы хотите откатить свою транзакцию, вам нужно сделать это endTransaction()без фиксации транзакции setTransactionSuccessful().

Вы можете получить подробную информацию о транзакции базы данных SQLite здесь

В твоем случае

Вы можете вызвать свою saveCustomer()функцию в блоках try и catch

db.beginTransaction();
try {
    saveCustomer();
    db.setTransactionSuccessful();
} catch {
    //Error in between database transaction 
} finally {
    db.endTransaction();
}
Дхармендра
источник
11
Вы должны добавить endTransactionв свой finally, а не в блок try.
VansFannel
6
@VansFannel, вы правы, наконец, лучшее место для закрытия транзакции базы данных. спасибо что сделали лучше.
Дхармендра
25

вы должны добавить endTransactionв свой finally, а не в свой блок попытки

 finally {
     myDataBase.endTransaction();
   }

Изменения будут отменены, если какая-либо транзакция завершится без пометки как чистая (путем вызова setTransactionSuccessful). В противном случае они будут совершены.

Лабиб Панампуллан
источник
1
Спасибо за информацию. В моем 'SaveCustomer () `я собираюсь вызвать' long n = dbAdapter.insertRecordsInDB (" Клиент ", null, initialValues); ' в 4 раза с разными записями. Будет ли он все откатывать, если возникнет ошибка даже в средней таблице. У меня 4 таблицы. Нужно добавить записи в 4 таблицы с разными записями.?
Kartheepan
17

Вставить запись с помощью транзакции, это очень быстро

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();
Пиюш
источник