Android数据库小技巧
一、执行SQL
相对于封装过的ContentProvider,使用原生SQL执行效率高,所以建议使用rawQuery、execSQL。
二、代理事务
假设继承SQLiteOpenHelper的数据库操作类为DatabaseHelper。当它有比较多的方法都需要事务操作时,可以提取这些方法为一个接口,如ITransactionHandler,之后让DatabaseHelper实现。这样即可通过代理来统一完成事务操作!
- /*
- * 代理执行需要事物处理的数据库操作方法
- *
- * 使用方式如下:
- * DatabaseHelper mHelper = new DatabaseHelper(context);
- * ITransactionHandler proxyHandler = (ITransactionHandler) TransactionHandler
- * .newProxyInstance(mHelper);
- * proxyHandler.resetDB();
- */
- public class TransactionHandler implements InvocationHandler {
- private static final String TAG = "TransactionHandler";
- public static final boolean LOGD = true;
- // 数据库操作帮助类
- private DatabaseHelper mDatabaseHelper;
- public TransactionHandler(DatabaseHelper helper) {
- this.mDatabaseHelper = helper;
- }
- // 返回代理类的实例
- public static Object newProxyInstance(DatabaseHelper helper) {
- // 直接使用Proxy的静态方法,返回代理实例
- return Proxy.newProxyInstance(helper.getClass().getClassLoader(),
- helper.getClass().getInterfaces(), new TransactionHandler(
- helper));
- }
- // 实现InvocationHandler接口方法,做自己的处理操作
- @Override
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- long start = System.currentTimeMillis(); // 开始时间戳
- Object result = null; // 方法返回结果
- SQLiteDatabase mDatabase = mDatabaseHelper.getWritableDatabase(); // 数据库操作对象
- mDatabase.beginTransaction(); // 开始事务
- try {
- // 代理执行数据库操作方法
- result = method.invoke(mDatabaseHelper, args);
- // 执行事务操作(到结束事务间不能再进行数据库操作)
- mDatabase.setTransactionSuccessful();
- } catch (Exception e) {
- e.printStackTrace();
- /*
- * 注意:这里设false是由于我每个操作数据方法都返回的是boolean。
- * 1)要增加不同的类型,可以用instanceof判断
- * 2)在invoke内出问题没返回result对象的情况,可考虑把异常分开捕获,或者判null
- */
- result = false;
- } finally {
- mDatabase.endTransaction(); // 结束事务
- }
- long end = System.currentTimeMillis(); // 结束时间戳
- if (LOGD)
- Log.d(TAG, "==" + method.getName() + " method lasts "
- + (end - start) + "ms==");
- return result;
- }
- }
更多代理内容,可以参看《Java 动态代理》。
三、文件SQL
执行一个SQL文件,以初始化数据等。可以把sql文件放在res/raw目录内。sql文注释方式,简易为“—”开头的行或“/*”“*/”开始的两行中间。
- public class SqlUtil {
- private final String commentPrefix = "--";
- private final String prefix = "/*";
- private final String suffix = "*/";
- private boolean isComment = false;
- private Context mContext;
- private SQLiteDatabase db;
- public SqlUtil(Context context, SQLiteDatabase db) {
- mContext = context;
- this.db = db;
- }
- // 执行raw内的简易sql文件
- public void execute(int rawId) {
- BufferedReader reader = null;
- try {
- InputStream is = mContext.getResources().openRawResource(rawId);
- reader = new BufferedReader(new InputStreamReader(is));
- for (String s; (s = reader.readLine()) != null;) {
- if (s.startsWith(commentPrefix)) {
- continue;
- }
- if (s.startsWith(prefix)) {
- isComment = true;
- continue;
- }
- if (s.startsWith(suffix)) {
- isComment = false;
- continue;
- }
- if (isComment) {
- continue;
- }
- db.execSQL(s);
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- if (null != reader) {
- reader.close();
- }
- } catch (IOException e) {
- }
- }
- }
- }
四、后记
其他的话,暂时应该没什么了…
本文转自winorlose2000 51CTO博客,原文链接:http://blog.51cto.com/vaero/900853,如需转载请自行联系原作者