Android数据库事务
我已经创建了一个数据库。我想做这笔交易Android数据库事务,android,sqlite,transactions,Android,Sqlite,Transactions,我已经创建了一个数据库。我想做这笔交易SaveCustomer()包含多条语句,用于将记录插入当时的Customer、CustomerControl、Profile、Payment表中 当用户调用SaveCustomer()方法时,该数据将进入这4个表。那么我如何处理该事务呢?如果一个表插入失败,则需要回滚所有内容。例如,当第三个表插入记录时,我得到一个错误,然后还需要回滚前两个表的插入记录 请参阅我的代码: public void saveCustomer(){ DBAdapter d
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;
}
}
public类DBAdapter扩展了SQLiteOpenHelper{
私有静态字符串DB_PATH=“/data/data/com.my.controller/databases/”;
私有静态最终字符串DB_NAME=“customer”;
私有SQLiteDatabase-myDataBase;
私有最终上下文myContext;
专用静态数据适配器MDB连接;
专用DBAdapter(上下文){
super(上下文,DB_名称,null,1);
this.myContext=上下文;
DB_PATH=“/data/data/”
+context.getApplicationContext().getPackageName()
+“/数据库/”;
//应用程序数据库的Android默认系统路径为
//“/data/data/mypackagename/databases/”
}
公共静态同步DBAdapter getDBAdapterInstance(上下文){
如果(mDBConnection==null){
mDBConnection=新的DBAdapter(上下文);
}
返回MDB连接;
}
public void createDataBase()引发IOException{
布尔值dbExist=checkDataBase();
if(dbExist){
//不执行任何操作-数据库已存在
}否则{
//通过调用下面的方法
//1)将在应用程序的默认系统路径中创建一个空数据库
//2)然后用数据库覆盖该数据库。
这是.getReadableDatabase();
试一试{
copyDataBase();
}捕获(IOE异常){
抛出新错误(“复制数据库时出错”);
}
}
}
私有布尔校验数据库(){
SQLiteDatabase checkDB=null;
试一试{
字符串myPath=DB_PATH+DB_NAME;
checkDB=SQLiteDatabase.openDatabase(myPath,null,SQLiteDatabase.OPEN\u READONLY);
}catch(sqlitee异常){
//数据库还不存在。
}
if(checkDB!=null){
checkDB.close();
}
return checkDB!=null?true:false;
}
私有void copyDataBase()引发IOException{
InputStream myInput=myContext.getAssets().open(DB_NAME);
字符串outFileName=DB_路径+DB_名称;
OutputStream myOutput=新文件OutputStream(outFileName);
字节[]缓冲区=新字节[1024];
整数长度;
而((长度=myInput.read(缓冲区))>0){
写入(缓冲区,0,长度);
}
//关闭溪流
myOutput.flush();
myOutput.close();
myInput.close();
}
/**
*打开数据库
*@SQLException
*/
public void openDataBase()引发SQLException{
字符串myPath=DB_PATH+DB_NAME;
myDataBase=SQLiteDatabase.openDatabase(myPath,null,SQLiteDatabase.OPEN\u READWRITE);
}
@凌驾
公共同步作废关闭(){
if(myDataBase!=null)
myDataBase.close();
super.close();
}
/**
*调用创建数据库,例如在运行时创建表
*/
@凌驾
public void onCreate(SQLiteDatabase db){
}
@凌驾
public void onUpgrade(SQLiteDatabase db,int-oldVersion,int-newVersion){
execSQL(“altertablewmpalmuploadcontroladdtestingint”);
}
公共无效升级数据库(){
onUpgrade(我的数据库,1,2);
}
公共光标选择RecordsFromDB(字符串tableName,字符串[]tableColumns,
字符串whereClase,字符串wherergs[],字符串groupBy,
字符串(具有,字符串排序依据){
返回myDataBase.query(tableName、tableColumns、whereClase、wherergs、,
groupBy、have、orderBy);
}
公共阵列列表
如果插入表数据时出现任何问题,我希望回滚
请帮帮我
谢谢
我查看了相同的相关问题:您应该在finally
中添加endTransaction
,而不是在try块中
finally {
myDataBase.endTransaction();
}
如果任何事务结束时没有更改,则更改将回滚
标记为干净(通过调用setTransactionSuccessful)。
否则,他们将被起诉
实际上你做错了。
若要将多条记录插入数据库或数据库,则必须设置“开始事务”
如果在其中一个数据库表中插入数据时出现问题,则必须从其他表回滚数据
比如说
你有两张桌子
A
B
现在您希望在这两个表中插入数据,但如果在表中插入数据时出现任何错误,则必须回滚事务
现在,您已成功地在表A中插入数据,并且正在尝试在表B中插入数据。现在,如果在表B中插入数据时出错,则必须从表A中删除相关数据,这意味着您必须回滚事务
如何在Android中使用数据库事务
如果要启动事务,有一个方法
如果要提交事务,有一种方法可以提交数据库中的值
如果启动了事务,则需要关闭事务,这样就有了一种方法可以结束数据库事务
现在有两个要点
如果你
db.beginTransaction();
try {
saveCustomer();
db.setTransactionSuccessful();
} catch {
//Error in between database transaction
} finally {
db.endTransaction();
}
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();