fred-ye / summary

my blog
43 stars 9 forks source link

[Android] 一种移动APP中DAO访问的设计思路 #28

Open fred-ye opened 9 years ago

fred-ye commented 9 years ago

今天把之前项目中关于SQLite的使用进行一个总结,相关的基本的概念性的东西就不说了。此处主要理一下,在一个APP中DB访问这一层的一种设计思路。直接上代码,先来一个直观的感觉。

一种设计思路

public class DBUtils extends SQLiteOpenHelper {
    private static final String TAG = "DBUtils";
    private static int version = 1;
    private static DBUtils instance = null;
    private static HashMap<String, String> tables = null;
    private static String DB_NAME = "test.db";
    private static final String DROP_TABLE_SQL = "DROP TABLE IF EXISTS %1$s";

    interface IUser {
        public static final String TABLE_NAME = "user";
        public static final String COLUMN_ID = "id";
        public static final String COLUMN_NAME = "name";
        public static final String COLUMN_EMAIL = "email";

        public static final String CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS %1$s("
                + COLUMN_ID
                + " INTEGER PRIMARY KEY AUTOINCREMENT,"
                + COLUMN_NAME
                + " TEXT,"
                + COLUMN_EMAIL           
                + " TEXT" + ")";
    }

    public static DBUtils getInstance(Context context) {
        if (instance == null) {
            instance = new DBUtils(context);
        }
        if (tables == null) {
            tables = new HashMap<String, String>();
            tables.put(IUser.TABLE_NAME, IUser.CREATE_TABLE_SQL);
        }
        return instance;
    }

    private DBUtils(Context context) {
        super(context, DB_NAME, null, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        try {
            db.beginTransaction();
            for (String str : tables.keySet()) {
                db.execSQL(tables.get(str));
            }
            db.setTransactionSuccessful();
        } catch (Exception e) {
            Log.i(TAG, "Create table error");
        } finally {
            db.endTransaction();
        }       
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        dropAllTables();
        onCreate(db);
    }
    public void dropAllTables() {
        SQLiteDatabase db = instance.getWritableDatabase();
        try {
            for (String tableName : tables.keySet()) {
                db.execSQL(String.format(DROP_TABLE_SQL, tableName));
            }
            db.setTransactionSuccessful();
        } catch (Exception e) {
            Log.i(TAG, "Create table error");
        } finally {
            db.endTransaction();
        }     
    }

    public void addUser(User user) {
        ContentValues values = new ContentValues();
        values.put(IUser.COLUMN_NAME, user.getName());
        values.put(IUser.COLUMN_EMAIL, user.getEmail());
        SQLiteDatabase db = instance.getWritableDatabase();
        db.insert(IUser.TABLE_NAME, null, values);
    }

    public void deleteByEmail(String email) {
        SQLiteDatabase db = instance.getWritableDatabase();
        db.delete(IUser.TABLE_NAME, "\"" + IUser.COLUMN_EMAIL + " = ? " + "\"", new String[] {email});
    }

    public void updateUserById (int id) {
        ContentValues values = new ContentValues();
        values.put(IUser.COLUMN_NAME, "userName");
        values.put(IUser.COLUMN_EMAIL, "userEmail");
        SQLiteDatabase db = instance.getWritableDatabase();
        db.update(IUser.TABLE_NAME, values, "id = ?", new String [] {id});
    }

}

相关解释

关于SQLIte的基本操作,网上一搜就一大堆。有过数据库开发经验的人可以说是马上就上手。不想做过多的说明。总结几点(没有测试,只做思路说明): 插入

采用ContentValues,每一个ContentValues实例实际上就是对应表里面的一条数据。如下操作:

public void addUser(User user) {
    ContentValues values = new ContentValues();
    values.put(IUser.COLUMN_NAME, user.getName());
    values.put(IUser.COLUMN_EMAIL, user.getEmail());
    SQLiteDatabase db = instance.getWritableDatabase();
    db.insert(IUser.TABLE_NAME, null, values);
}

删除

public void deleteByEmail(String email) {
    SQLiteDatabase db = instance.getWritableDatabase();
    db.delete(IUser.TABLE_NAME, "\"" + IUser.COLUMN_EMAIL + "= ? " + "\"", new String[] {email});
}

如果是删除一整张表中的数据就用

instance.getWritableDatabase().delete(IUser.TABLE_NAME, null, null);

更新

实际上和插入的操作差不多。

ContentValues values = new ContentValues();
values.put(IUser.COLUMN_NAME, "userName");
values.put(IUser.COLUMN_EMAIL, "userEmail");
SQLiteDatabase db = instance.getWritableDatabase();
db.update(IUser.TABLE_NAME, values, "id = ?", new String [] {id});

查询

查询操作实际上就是利用Cursor.

Cursor localCursor = instance.getReadableDatabase().query(IUser.TABLE_NAME, null, "email = ?", new String[] { email }, null, null, null);

然后再就是移动Cursor,取值。

说明

在SQLite的使用过程中,没有必要每一次在操作完数据库后就关闭数据库连接,否则会造成莫名的Exception.通常应用中操作数据库都是采用新开一个线程来执行,有可能有两个线程都在操作数据库。第一个线程操作完后若关闭了数据库连接,第二个线程还正在操作数据库,就会出问题了。当然关闭数据库连接出现的Exception并不局限于这种情况,但是我们在使用时,没有手动关闭数据库连接是不会有问题,一旦手动关闭就会出现一些莫名其妙的问题。其中缘由还需Rearch。

今天无意中发现了这篇博客,可能和之前碰到的关闭数据库连接会产生Crash有些关系,先记录在这, 抽时间研究一下[2015-06-03]