web-dev-qa-db-ja.com

Androidデータベーストランザクション

データベースを作成しました。トランザクションを行いたいです。 SaveCustomer()には、その時点でCustomer, CustomerControl, Profile, Paymentテーブルにレコードを挿入するための複数のステートメントが含まれています。

ユーザーがSaveCustomer()メソッドを呼び出すと、そのデータはこれらの4つのテーブルに送られます。どうすればトランザクションを実行できますか? 1つのテーブルの挿入が失敗した場合、すべてをロールバックする必要があります。たとえば、3番目のテーブルがレコードを挿入するときにエラーが発生した場合、前の2つのテーブルの挿入レコードもロールバックする必要があります。

私のコードを参照してください:

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のデータベースロックの問題

テーブルデータの挿入時に問題が発生した場合は、ロールバックします。

私を助けてください

ありがとう。

私はこの同じ関連質問を見ました:

81
Kartheepan

実際、あなたは間違っています。データベースに挿入する複数のレコードがある場合、またはデータベーステーブルのいずれかにデータを挿入する際に問題がある場合に他のテーブルからデータをロールバックする必要がある場合は、トランザクションの開始を設定する必要があります。

例えば

2つのテーブルがあります

  1. A
  2. B

ここで、これら2つのテーブルにデータを挿入しますが、テーブルにデータを挿入するときにエラーが発生した場合、トランザクションをロールバックする必要があります。

これで、テーブルAにデータを正常に挿入し、テーブルBにデータを挿入しようとしています。テーブルBにデータを挿入するときにエラーが発生した場合は、テーブルAから関連データを削除する必要があります。トランザクションをロールバックする必要があります。

Androidでデータベーストランザクションを使用する方法

  1. トランザクションを開始する場合、メソッドがあります beginTransaction()
  2. トランザクションをコミットする場合は、データベース内の値をコミットするメソッド setTransactionSuccessful() があります
  3. トランザクションを開始した場合、データベーストランザクションを終了するメソッド endTransaction() があるため、トランザクションを閉じる必要があります

今、2つの主要なポイントがあります

  1. トランザクションを成功に設定したい場合、 setTransactionSuccessful() を記述し、 endTransaction() の後に beginTransaction() を記述する必要があります。
  2. トランザクションをロールバックする場合は、 endTransaction() でトランザクションをコミットせずに setTransactionSuccessful() にする必要があります。

here からSQLiteデータベーストランザクションに関する詳細情報を取得できます。

あなたの場合

TryブロックとcatchブロックでsaveCustomer()関数を呼び出すことができます

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

tryブロックではなく、endTransactionfinallyを追加する必要があります

 finally {
     myDataBase.endTransaction();
   }

(setTransactionSuccessfulを呼び出して)クリーンとしてマークされずにトランザクションが終了した場合、変更はロールバックされます。そうでなければ、それらはコミットされます。

25

トランザクションを使用してレコードを挿入、これは非常に高速です

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