Android数据库交易

我创build了一个数据库。 我想做交易。 SaveCustomer()包含多条语句,当时将logging插入到Customer, CustomerControl, Profile, Payment表中。

当用户调用SaveCustomer()方法时,那么这些数据将会转到这4个表。我怎样才能做这个事务呢? 如果一个表插入失败,那么需要回滚一切。 例如,当第三个表插入logging时,我得到一个错误,那么还需要回滚前两个表的插入logging。

看我的代码:

 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数据库locking问题 。

如果插入表数据时发生任何问题,我想回滚。

请帮帮我

谢谢。

我看了这个相同的相关问题:

其实你做错了 如果有多个logging要插入到数据库中,或者如果在数据库表中插入数据时出现问题,则必须从其他表中回滚数据。

例如

你有两张桌子

  1. 一个

现在,您要在这两个表中插入数据,但是如果在将数据插入表中时出现错误,则必须回滚事务。

现在你已经成功地在表A中插入数据,现在你正试图在表B中插入数据。现在如果在表B中插入数据的时候出现错误,那么你必须删除表A中的相关数据,这意味着你必须回滚交易。

如何在Android中使用数据库事务

  1. 如果你想开始交易有一个方法beginTransaction()
  2. 如果你想提交事务,有一个方法setTransactionSuccessful()将提交数据库中的值
  3. 如果你已经开始了事务,你需要closures这个事务,所以有一个endTransaction()方法可以结束你的数据库事务

现在有两个要点

  1. 如果要设置事务成功,则需要在beginTransaction()之后编写setTransactionSuccessful()endTransaction() beginTransaction()
  2. 如果你想回滚你的事务,那么你需要endTransaction()而不用setTransactionSuccessful()提交事务。

您可以从这里获得有关SQLite数据库事务的详细信息

在你的情况

你可以在try和catch块中调用你的saveCustomer()函数

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

你应该在你的finally块中添加endTransaction ,而不是在你的try块中

  finally { myDataBase.endTransaction(); } 

如果任何事务没有被标记为干净(通过调用setTransactionSuccessful),则更改将被回滚。 否则,他们将承诺。

使用事务插入logging,这是非常快的

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