Giao dịch cơ sở dữ liệu Android


84

Tôi đã tạo một cơ sở dữ liệu. Tôi muốn thực hiện Giao dịch. SaveCustomer()chứa nhiều hơn một câu lệnh để chèn bản ghi vào Customer, CustomerControl, Profile, Paymentbảng tại thời điểm đó.

Khi người dùng gọi SaveCustomer()phương thức thì dữ liệu đó sẽ chuyển đến 4 bảng này. Vì vậy, tôi có thể thực hiện giao dịch bằng cách nào? Nếu một lần chèn bảng không thành công thì cần khôi phục mọi thứ. Ví dụ: khi bảng thứ 3 chèn bản ghi, tôi gặp lỗi, sau đó cần khôi phục lại bản ghi chèn của hai bảng trước đó.

Xem mã của tôi:

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

}

Tương tự như vậy tuyên bố khác cũng có.

Mã DBAdpter là:

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

Đây là mã đầy đủ:

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

}

vấn đề khóa cơ sở dữ liệu trong HTC Desire .

Tôi muốn quay lại nếu có bất kỳ sự cố nào xảy ra khi chèn dữ liệu bảng.

Làm ơn giúp tôi

Cảm ơn.

Tôi đã xem câu hỏi liên quan tương tự này:

Câu trả lời:


279

Thực ra bạn đang làm sai. Bạn phải đặt bắt đầu giao dịch nếu bạn có nhiều bản ghi để chèn vào cơ sở dữ liệu hoặc nếu bạn phải khôi phục dữ liệu từ bảng khác nếu có sự cố khi chèn dữ liệu vào một trong các bảng cơ sở dữ liệu.

Ví dụ

Bạn có hai bảng

  1. A
  2. B

Bây giờ bạn muốn chèn dữ liệu vào hai bảng này nhưng bạn sẽ phải khôi phục giao dịch nếu bạn sẽ gặp bất kỳ lỗi nào tại thời điểm chèn dữ liệu trong bảng.

Bây giờ bạn đã chèn thành công dữ liệu trong bảng A và bây giờ bạn đang cố gắng chèn dữ liệu trong bảng B. Bây giờ nếu bạn gặp lỗi tại thời điểm chèn dữ liệu trong bảng B thì bạn phải xóa dữ liệu có liên quan khỏi bảng A nghĩa là bạn phải khôi phục giao dịch.

Cách bạn có thể sử dụng giao dịch cơ sở dữ liệu trong Android

  1. Nếu bạn muốn bắt đầu giao dịch, có một phương pháp beginTransaction()
  2. Nếu bạn muốn cam kết giao dịch, có một phương thức setTransactionSuccessful()sẽ cam kết các giá trị trong cơ sở dữ liệu
  3. Nếu bạn đã bắt đầu giao dịch, bạn cần phải đóng giao dịch để có một phương pháp endTransaction()sẽ kết thúc giao dịch cơ sở dữ liệu của bạn

Bây giờ có hai điểm chính

  1. Nếu bạn muốn giao dịch đặt thành công bạn cần phải viết setTransactionSuccessful()và sau đó endTransaction()sau khibeginTransaction()
  2. Nếu bạn muốn khôi phục giao dịch của mình thì bạn cần phải endTransaction()thực hiện giao dịch trước setTransactionSuccessful().

Bạn có thể lấy thông tin chi tiết về giao dịch cơ sở dữ liệu SQLite từ đây

Trong trường hợp của bạn

Bạn có thể gọi saveCustomer()hàm của mình trong khối thử và bắt

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

11
Bạn nên thêm endTransactionvào cuối cùng, không phải trong khối thử của bạn.
VansFannel

6
@VansFannel cuối cùng bạn đã đúng là nơi tốt nhất để đóng giao dịch cơ sở dữ liệu. cảm ơn vì đã làm cho nó tốt hơn.
Dharmendra

25

bạn nên thêm endTransactionvào của bạn finally, không phải trong khối thử của bạn

 finally {
     myDataBase.endTransaction();
   }

Các thay đổi sẽ được khôi phục nếu bất kỳ giao dịch nào kết thúc mà không được đánh dấu là sạch (bằng cách gọi setTransactionSuccessful). Nếu không họ sẽ cam kết.


1
Cảm ơn vì thông tin. Trong 'SaveCustomer () `của tôi, tôi sẽ gọi' long n = dbAdapter.insertRecordsInDB (" Khách hàng ", null, ban đầuValues); ' trong 4 thời gian với các bản ghi khác nhau. Nó sẽ khôi phục mọi thứ, nếu có bất kỳ lỗi nào xảy ra ngay cả trong bảng giữa. Tôi có 4 bảng. Cần thêm các bản ghi trong 4 bảng với các bản ghi khác nhau.?
Kartheepan

17

Chèn bản ghi bằng giao dịch, việc này rất nhanh

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();
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.