如何将Android数据库操作通用化(三)

      • 概述
      • 悠悠绿水傍林侵日落观山四望回
      • 幽林古寺孤明月冷井寒泉碧映台
      • 鸥飞满浦渔舟泛鹤伴闲亭仙客来
      • 游径踏花烟上走流溪远棹一篷开

概述

一个不小心都写了三篇了,也不知道大家还看得懂不?如果看不懂最好给我留个言,我好下一次改正。

接着上次的说,准备工作都已经做好了,现在咱们就要开始着手解决阻挡Android数据库操作通用化的五个问题了。

我们先回顾一下问题:
问题1:表名的获取
问题2:如何将实体中的数据,按照对应关系导入到数据库中
问题3:明确实体中主键是谁?获取到主键中封装的值
问题4:如何将数据库中表的列的数据,按照对应关系,封装到实体中
问题5:实体的对象创建

悠悠绿水傍林侵,日落观山四望回。

问题当然是一个一个解决,这样才有效率,那么第一个问题来了:表名如何获取

通常情况下,解决一个问题时,都会以一个方法或者函数开始,这次也不例外,我们先给一个壳子:

/** 问题一:表名的获取 **/
public String getTableName() {
    return null;
}

一切充满了希望,也显得那么自然。现在我们就要开始思考一些关于如何获取表名的问题了。

在实际开发中,每一个数据库表,都会对应着一个具体的实体。就好像news表对应着News类。看看它们,是不是名字好相似?只不过一个是首字母大写,另一个是全小写。于是我们心底这么想,如果我们能够通过“实体”拿到表名就好了

既然有了路走走看,就知道走的通还是走不通了。

我们可以提出两个方案:
① 如果能够获取到实体,那么我们就能够获取到实体的简单名称,然后只需要将首字母小写就是表名了。但是,这样的缺点也很明显,这要求数据库定义表的名称和实体的名称基本一致,这样就会导致我们定义的实体名称收到限制。例如:定义了news表,那么对应的实体就只能是News了。
② 利用注解,这样就可以让实体的名称和数据库表的名称之间的关系脱离,两者互不干涉。缺点也是显而易见,编码难度增加,(嘿嘿),不过谁叫咱们是有经验的开发人员,就选这种了。

如果有同学注解遗忘掉了,或者还不是很清晰,可以参看我的这篇文章:http://blog.csdn.net/biezhihua/article/details/43783165

幽林古寺孤明月,冷井寒泉碧映台。

明确了道路,一路向前就可以了。

接下来就要使用到注解和反射什么的了!!是不是有点小激动~哈哈~

接下来的任务,就是给News实体类增加一个注解了,增加注解的目的则是,将数据库表和对应实体之间的关系确定下来。请看代码:

// 注解的作用:将数据库表和对应的实体确定下来。
@TableName(DBHelper.TABLE_NEWS_NAME)
public class News {
    private int id;
    private String title;
    private String summary;
}

看起来像模像样的,但是@TableName(DBHelper.TABLE_NEWS_NAME)这句是什么? 谁能告诉我?

这句就是我们写的注解了,但是,此时我们还没有创建出来,但是不要紧,如果你使用的是Eclipse,请选中这行Ctrl+1,就可以自动创建了,这么高大上,是不是被震到了!(^ω^)。请看具体的TableName代码:

/**
 * 制定了实体和数据库中表的对应关系
 */
@Target(ElementType.TYPE) // 指定放置的位置
@Retention(RetentionPolicy.RUNTIME) // 指定存活时间
public @interface TableName {
    /**
     * 数据库中的表名,此处可以存放值
     */
    String value();
}

一切都是这么简单明了,让人心旷神怡。现在,注解已经创建好,实体上的注解也已经添加完毕,并且传入了表名。接下来在getTableName方法中,继续填写代码就好了。

获取表名依旧分为两步:
① 获取到对象的实体 - 这个是问题五
② 获取实体头上的注解,依据value的设置值,确定操作的表。

在伪代码的第一步是获取到对象的实体,经过查看,这个恰好是第五个问题,我们先放着,写一个空方法来代表。

/**
 * 问题五:实体对象的创建
 */
private M getInstance() {
    return null;
}

具体的getTableName()方法代码如下所示:

public String getTableName() {

    // 伪代码:
    // ① 问题五:获取到对象的实体
    M m = getInstance();
    // ② 获取实体头上的注解,依据value的设置值,确定操作的数据库表
    // 需要注意的,想要在“运行时”获取到注解的信息,给注解设置存活时间。
    TableName tableName = m.getClass().getAnnotation(TableName.class); // annotationType 注解的类型
    // 为了安全起见,判断注解的合法性;合法则返回value值
    if (tableName != null) {
        return tableName.value();
    }
    return null;
}

有了这个方法,BaseDaoSupport中的delete方法也就可以写出来了,依旧很简单,请看代码:

@Override
public int delete(Serializable id) {
    return db.delete(getTableName(), DBHelper.TABLE_ID + "=?", new String[] { id.toString() });
}

小结:其实呢,在表名的获取中,我们就是利用注解去解决了一个事,表和实体是一一对应的,它们之间的对应关系是什么。(TableName)

鸥飞满浦渔舟泛,鹤伴闲亭仙客来。

是时候表演真正的技术了!!(╰_╯)#

接下来该解决第二个问题了,如何将实体中的数据,按照对应关系导入到数据库中。

回想一下第一个问题的解决,其实就是利用注解解决了,表和实体之间的对应关系。以此类推,第二个问题也是要求将实体中的数据,按照对应关系导入到数据库中。一样的思路,继续往下延续,可以再为实体的字段一个注解,来体现和数据库表中列的对应关系。请看代码:

/**
 * 制定了实体的子对岸和数据库表中列的对应关系
 */
@Target(ElementType.FIELD) // 指定放置的位置
@Retention(RetentionPolicy.RUNTIME) // 指定存活时间
public @interface Column {
    String value();
}

只要字段上有这个注解的,肯定是和数据库表中的列有对应关系,接下来为实体的字段添加相应的注解,并传入列名。请看代码:

// 注解的作用:将数据库表和对应的实体确定下来。
@TableName(DBHelper.TABLE_NEWS_NAME)
public class News {

    // 指定了实体和数据库中表的对应关系
    @Column(DBHelper.TABLE_ID)
    private int id;

    @Column(DBHelper.TABLE_NEWS_TITLE)
    private String title;

    @Column(DBHelper.TABLE_NEWS_SUMMARY)
    private String summary;
}

准备工作已经做好了,接下来就要填写insert中的代码了,此处新建了一个fillColumn(M m, ContentValues values)方法,把实体M字段值和字段上Column(XXX)注解中传入的列名,用values.put(key,value)方法填入到valeus中,以便insert中填写数据。代码如下:

@Override
public long insert(M m) {
    ContentValues values = new ContentValues();

    // m代表数据源,vlaues是数据导入的目标
    fillColumn(m, values);

    return db.insert(getTableName(), null, values);
}

代码很简单,关键在于fillColumn(m, values);的数据填充。通过使用反射技术,获取到M实例的所有字段集合,再依次拿到每个字段的值和每个字段注解的值,并填充到values中,请看代码:

/**
 * 问题二:如何将实体中的数据,按照对应关系导入到数据库中
 *
 * @param m 数据源
 * @param values 是数据导入的目标
 */
public void fillColumn(M m, ContentValues values) {

    // 获取m上所有的字段
    Field[] fields = m.getClass().getDeclaredFields();

    for (Field field : fields) {
        // 设置访问权限
        field.setAccessible(true);
        // 获取字段头上的注解
        Column column = field.getAnnotation(Column.class);
        if (column != null) {
            try {
                String key = column.value(); // 获取注解中,指定的列名
                String value = field.get(m).toString(); // 获取字段值
                // 填写数据
                values.put(key, value);
            } catch (IllegalArgumentException e) {
                throw new RuntimeException("字段不属于m实例");
            } catch (IllegalAccessException e) {
                throw new RuntimeException("没有访问字段域的权限");
            }
        }
    }
}

总结:只要掌握了思路和方法,整洁、清晰的代码,写起来也不是那么困难。

游径踏花烟上走,流溪远棹一篷开。

人生不相见,动如参与商.

今夕复何夕,共此灯烛光.

少壮能几时,鬓发各已苍.

访旧半为鬼,惊呼热中肠.

焉知二十载,重上君子堂.

昔别君未婚,儿女忽成行……

时间: 2024-10-01 06:53:50

如何将Android数据库操作通用化(三)的相关文章

如何将Android数据库操作通用化(一)

概述 在开始考虑Android的数据库操作之前,我们先回想一下Web方面的数据库操作.如果我们只是停留在JDBC的简单使用和封装上(比如纯JDCB,或者DBUtils),即使我们对数据库的增删改查操作进行了接口的抽取,代码依旧会和业务有很强的耦合性. 经过我们分析,解除耦合性的关键在于如何解决自动映射"实体类 与 数据库表"之间的对应关系.如果能够做到这一步,那么我们就能够更好的解耦了,也能降低我们的代码重复率. 如果我们再跨前一步,使用更为优秀的框架(比如:Hibernate),这一

数据库操作通用类

DataBase.java 说明: 1. 此类包含对数据库的查询,删除,更新操作.     2. 可以实现对大文本对象的增删改.     3. 利用自建的数据库连接池类, 得到数据库连接.     4. 可以利用Tomcat 自带的连接池, 得到数据库连接 变量:     1. 数据库连接 变量名     : conn 应用范围   : protect 变量类型   : Connection 数据库连接 初始值     : null 是否Static :  否     2. 声明语句 变量名  

Android数据库操作_表格显示

Android数据库操作_表格显示 显示表格布局 完成后效果如下: 首先需要一个主布局文件main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation=&quo

android菜鸟学习笔记20----Android数据存储(四))Android数据库操作

Android内置了一个名为SQLite的关系型数据库,这是一款轻量型的数据库,操作十分简便.SQLite与别的数据库不同的是,它没有数据类型.可以保存任何类型的数据到你所想要保存的任何表的任何列中.但它又支持常见的类型比如: NULL, VARCHAR, TEXT, INTEGER, BLOB, CLOB...等. 唯一的例外是:integer primary key 此字段只能存储64位整数. 在JAVA项目中,要使用JDBC操作数据库需要加载数据库驱动,连接数据库等操作.Android简化

C#数据库操作通用方法类

平时使用的数据库操作类整理更新后备份,记录下来以供以后使用,并顺便分享给大家一起交流.直接上源码: 整个底层操作方法分为4个类,基础方法类:SqlBase 基础工具类:SqlTool 日志类:DbLog  和MSSQL操作类:MsSqlHelper. 由于平时工作未用到其他类型数据库,因此未整理其他数据库的操作类,以后用到的话会进行更新. 首先是通用的数据库底层操作方法整理: /// <summary> /// 数据库操作基础方法类 /// </summary> public cl

android数据库操作之直接读取db文件

在对数据库操作时,常用的有两种方法: 1.在代码中建库.建表: 2.直接将相关库.表建立好,将db文件拷贝至assets目录下: 现在来看看第二种方法: private String GetDataBasePath(Context context) { String packageName = context.getPackageName(); //Log.i("PackName", packageName); // String DB_PATH = String.format(&qu

android数据库操作

package cn.hackcoder.beautyreader.db; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; /** * Created by hackcoder on 15-1-25. */ public class Data

android 数据库操作详解

请看郭大神的八篇专栏,包含sql语句  android封装的databasehelper 和郭大神自己的LitePal  三种使用详解 http://blog.csdn.net/column/details/android-database-pro.html

数据库操作通用方法类

public class DbMethods { /// <summary> /// 获取数据库 /// </summary>zlf 2014-12-11 /// <param name="dbCode">用户:u 项目:p 捐赠:d 公共:c 活动:a 日志:l</param> public static Database GetDb(string dbCode) { Database db = null; switch (dbCode