面试题答案
一键面试开启事务
在Android中,使用SQLiteDatabase
类开启事务可以通过调用beginTransaction()
方法,示例代码如下:
SQLiteDatabase db = yourSQLiteOpenHelper.getWritableDatabase();
try {
db.beginTransaction();
// 在此处执行数据库操作
} catch (Exception e) {
e.printStackTrace();
} finally {
// 处理事务提交或回滚
}
提交事务
事务中的所有操作执行成功后,调用setTransactionSuccessful()
方法标记事务成功,并通过endTransaction()
方法提交事务,示例代码如下:
SQLiteDatabase db = yourSQLiteOpenHelper.getWritableDatabase();
try {
db.beginTransaction();
// 执行数据库操作
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
db.endTransaction();
}
回滚事务
如果在事务执行过程中出现异常,不需要显式调用回滚方法,因为当事务未标记为成功(未调用setTransactionSuccessful()
)就调用endTransaction()
时,事务会自动回滚。示例代码如下:
SQLiteDatabase db = yourSQLiteOpenHelper.getWritableDatabase();
try {
db.beginTransaction();
// 执行数据库操作,可能会抛出异常
} catch (Exception e) {
e.printStackTrace();
} finally {
db.endTransaction(); // 由于未调用setTransactionSuccessful(),事务回滚
}
大量数据插入场景下结合事务处理的性能优化策略
- 批量插入:不要单个数据逐条插入,而是将多条数据组装成一个
ContentValues
数组或List
,然后使用execSQL
方法结合INSERT INTO... VALUES
的批量插入语法,或者使用bulkInsert
方法(如果数据库版本支持)。例如:
ContentValues[] valuesArray = new ContentValues[100];
for (int i = 0; i < 100; i++) {
ContentValues values = new ContentValues();
values.put("column1", "value1");
values.put("column2", "value2");
valuesArray[i] = values;
}
db.beginTransaction();
try {
for (ContentValues values : valuesArray) {
db.insert("your_table", null, values);
}
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
db.endTransaction();
}
- 减少SQL语句编译次数:在事务内尽量复用已编译的SQL语句。例如,使用
SQLiteStatement
进行预编译,示例代码如下:
String insertSql = "INSERT INTO your_table (column1, column2) VALUES (?,?)";
SQLiteStatement statement = db.compileStatement(insertSql);
db.beginTransaction();
try {
for (int i = 0; i < 100; i++) {
statement.bindString(1, "value1");
statement.bindString(2, "value2");
statement.executeInsert();
}
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
statement.close();
db.endTransaction();
}
- 合理设置事务隔离级别:根据业务需求选择合适的事务隔离级别。默认的隔离级别可能会导致不必要的锁竞争,影响性能。例如,在一些读多写少的场景下,可以适当降低隔离级别以提高并发性能,但要注意数据一致性问题。
- 及时释放资源:事务结束后,及时关闭相关的数据库操作对象(如
Cursor
、SQLiteStatement
等),避免资源泄漏和潜在的性能问题。