Orm之Reflect(二)

Orm_Reflect_DB——Reflect(二)

ORM系列章节(点击查阅)

一、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也有了,准备工作齐全,可以开始数据库操作方法的封装了。
我们这里重点讲一下insert操作,其他可通过阅读源码获得:Orm_Reflect_DB
这里面重点代码都在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,欢迎大家指正,并提出修改意见,下一章我会大概讲解一下如何在自己项目中使用。虽然东西很小,但很实用,希望能对您有帮助。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值