Orm_Reflect_DB——Reflect(二)
ORM系列章節(點擊查閱)
前面講了Orm以及XMl解析,並回顧了Reflect的幾個常用知識點,那麼現在我們即將進入正題,將XMl、實體類、數據庫字段、Reflect結合起來實現數據庫操作類的封裝,這也是整個小框架的核心所在。
首先我們新建dao目錄並創建BaseDao類用來封裝數據庫操作:
先貼構造函數代碼如下:
/**
* @param helper
*/
public BaseDao(BaseDatabaseHelper helper, Class<T> beanClass) {
this.db = helper.getWritableDatabase();
this.beanClass = beanClass;
//根據文件名獲取對應orm
this.orm = DBConfig.mapping.get(beanClass.getSimpleName() + ".orm.xml");
}
這裏我們傳入一個BaseDatabaseHelper對象(我們Orm部分提到過),這個很好理解,用於初始化SQLiteDatabase,進行數據操作。那麼另一個Class<T>這個對象類型又是什麼呢,前一章我們有講過Reflect的常用知識點,其中不管是獲取Java類中的方法、成員變量還是實例化類都需要一個類的對象,那就是Class<?>,我們這裏有用到泛型,主要用於限定對象類型,也方便代碼拓展;另一個orm參數即爲XMl解析後得到的對象,通過文件名獲取在mapping集合中相對應的orm。Class<?>有了,SQLiteDatabase有了,Orm也有了,準備工作齊全,可以開始數據庫操作方法的封裝了。
這裏面重點代碼都在putValues(T t)這個方法中,我先貼一下ContentValues集合添加對象的方法:
public long insert(T t) {
long length = -1;
if (db != null) {
db.beginTransaction();
try {
//將參數封裝到ContentValues集合中
ContentValues values = putValues(t);
length = db.insert(orm.getTableName(), null, values);
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
db.endTransaction();
}
}
return length;
}
看到這裏我們可以知道的是第一個參數是String類型,代表數據庫表中的字段名,第二個參數則是字段對應的值,那麼問題來了,我們只傳入一個T對象,怎麼獲取到字段名和字段對應的值,還有這個put方法又改用哪個,是不是頭暈了。不用怕,我們一個個解決問題,首先怎麼獲取到字段名,其實簡單,我們的構造函數中得到Orm屬性中不就包含了Key和Item對象,字段名不就是他們兩的成員變量,那麼fildName就解決了,至於字段對應的值我們是不是可以通過反射的方式從傳進來的T對象中獲取,put方法同理,說了這麼多,還是貼代碼實在: private ContentValues putValues(T t) throws Exception {
//因爲無法確定values.put()參數類型,這裏用到反射調用values的put方法
ContentValues values = new ContentValues();
Key key = orm.getKey();
//判斷key時候爲自增長,否才進行賦值
if (!key.isIdentity()) {
//通過反射獲取ContentValues的put方法
Method put = values.getClass().getDeclaredMethod("put",
new Class[]{String.class, Class.forName(key.getType())});
//獲取實體類的成員變量
Field field = beanClass.getDeclaredField(key.getProperty());
//設置不做權限檢查(private、protect等都可以取到值)檢查
field.setAccessible(true);
//獲取成員變量的值
Object value = field.get(t);
put.invoke(values, key.getColumn(), value);
}
for (Item item : orm.getItems()) {
Method put = values.getClass().getDeclaredMethod("put",
new Class[]{String.class, Class.forName(item.getType())});
Field field = beanClass.getDeclaredField(item.getProperty());
field.setAccessible(true);
Object value = field.get(t);
put.invoke(values, item.getColumn(), value);
}
return values;
}
是不是屌爆了,用過Orm或者Gson解析的是不是發現這種直接傳對象集合就能得到結果的方法很眼熟,不錯,看了這篇文章你會發現,其實就這麼簡單。
方法也封裝好了,接下來我們要試下結果如何,黑貓、白貓,能抓到老鼠纔是好貓。
我們需要建立Student表專屬的dao類,方便建立model以及解耦:
public class StudentDao extends BaseDao<Student> {
public StudentDao(BaseDatabaseHelper helper) {
super(helper,Student.class);
// TODO Auto-generated constructor stub
}
public Orm getOrm(){
return super.getOrm();
}
}
注意這裏我們需要將Student的字節碼文件屬性傳給BaseDao類,建立自己的專屬dao,至於界面怎麼寫我就不多說了,畢竟跟我們要講的東西關係不大,直接貼效果圖:
我將其中公共部分的代碼剝離了出來,寫成了一個library,包含在源碼中:Orm_Reflect_DB,歡迎大家指正,並提出修改意見,下一章我會大概講解一下如何在自己項目中使用。雖然東西很小,但很實用,希望能對您有幫助。