注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

和申的个人主页

专注于java开发,1985wanggang

 
 
 

日志

 
 

Android通用DAO(数据访问对象)设计和实现  

2015-08-19 09:28:32|  分类: 安卓 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

1、前言:


在Android的应用开发中,往往会涉及到许多数据的存储和交互,其中,内嵌的sqlite数据库会作为首选的方案,在一些涉及比较多的数据交互情境中,通常表现为表的数量比较多,我们就有必要开发一个比较通用的数据访问框架了。

2、设计目标:

(1):能够方便地创建表和对象的对应关系.[这里我们以注解的方式实现]

(2):能够以统一的方式方便的进行数据的增删查改.

也就是能够使用类似Hibernate等框架的使用: 如增加一条记录的使用习惯:

  TUser user = new TUser(); user.setId("id"); userDao.insert(user).

3、实现结果初体验:


(1):描述表和对象关系:

@Table(name = "t_user")

public class TUser {    

@Column(name="user_id",type=Column.TYPE_BOOLEAN,isPrimaryKey=true)


    private Integer userId;


     


    @Column(name="user_name",type=Column.TYPE_STRING)


    private String userName;


    /**


     * 必须提供无参构造函数


     */

    public TUser() {}

    public TUser(String userName) {


        this.userName = userName;


    }

        //getter

        //setter

}



(2):增删查改

//Insert An Object

IBaseDao<TUser> userDao = DaoFactory.createGenericDao(this, TUser.class);

userDao.insert(new TUser("AAAA"));

//Insert Object List

List<TUser> insertUserList = new ArrayList<TUser>();

for(int i = 0; i<10;++i){

    insertUserList.add(new TUser("BBB"+i));

}

userDao.batchInsert(insertUserList);

//只有一条记录的查找

List<TUser> userList = userDao.queryByCondition("user_name=?", "AAAA");

//InsertOrUpdate

userDao.insertOrUpdate(new TUser("AAAA"), "user_name"); //update where user_name='AAAA'

userDao.insertOrUpdate(new TUser("CCCC"), "user_name"); //insert CCCC

实现结果符合了设计目标,用起来还是很方便的.

4、实现类和接口说明:


以下内容应结合代码看.[com.darcy.dao]包内,完整的代码请点击这里获取。

(1)总览:

.DaoFactory: 提供了集中获取数据操作对象工厂,并缓存该对象.

.DBUtils: 封装了Android API提供的数据库实现

.IBaseDao: 面向用户的接口

.GenericDao: IBaseDao的实现类

.GenericDao.DBTransction: 封装了对事务的操作.

.QueryResult: 对查询结果一行记录的封装类.封装后的类可以尽最大努力取到你想要的值,如数据库中存储1.0为text类型,则通过QueryResult.getIntProperty()可以获得正确的整型值1

.SqlHelper: 拼接SQL语句AND两个对等对象之间直交换的辅助类

.Table: 表和对象的映射注解类

(2)接口设计:

public interface IBaseDao<T> {

    /**

     * 创建表

     */

    void createTable();

    /**

     * 插入一条记录

     * 

     * @param model

     * @return

     */

    boolean insert(T model);

    /*

     * 插入多条记录

     * 

     * @param model

     * @return

     */

    boolean batchInsert(List<T> dataList);

    /**

     * 更新记录

     * 

     * @param model

     * @param whereClaus

     * @param whereArgs

     * @return

     */

    boolean update(T model, String whereClause, String... whereArgs);

    /**

     * 决定是否insert或者Update

     * @param model

     * @param bindColumnNames 绑定的列名 ,默认是主键

     * @return

     */

    boolean insertOrUpdate(T model,String... bindColumnNames);

    /**

     * 删除记录

     *

     * @param whereClause

     * @param whereArgs

     * @return

     */

    boolean delete(String whereClause, String... whereArgs);

    /**

     * 删除全部记录

     * @return

     */

    boolean deleteAll();


    /**

     * 根据条件查询

     * 

     * @param whereClause

     * @param whereArgs

     * @return

     */

    List<T> queryByCondition(String selection, String... selectionArgs);

 

    /**

     *  根据条件查询

     * @param columns

     * @param selection

     * @param orderBy

     * @param selectionArgs

     * @return

     */

    List<T> queryByCondition(String[] columns, String selection,

            String orderBy, String... selectionArgs);


    /**

     * 根据条件查询

     * @param columns

     * @param selection

     * @param groupBy

     * @param having

     * @param orderBy

     * @param selectionArgs

     * @return

     */

    List<T> queryByCondition(String[] columns, String selection,

            String groupBy, String having, String orderBy,

            String... selectionArgs);


    /**

     * 只有唯一一条记录的查询

     * 

     * @return 如果没有则返回null

     */

    T queryUniqueRecord(String selection,String... selectionArgs);


    /**

     * 自定义查询

     * @param sql

     * @param bindArgs

     * @return

     */

    List<QueryResult> execQuerySQL(String sql, String... bindArgs);

    /**

     * 执行Insert/Update/Delete等其他非查询SQl

     * @param sql

     * @param bindArgs

     * @return

     */

    boolean execUpdateSQL(String sql, Object... bindArgs);

}



为什么这么多queryByCondition? 最小接口原则,这样在用的时候提供更多选择,代码可变得更加精简一些.

为什么提供execQuerySQL: 为了支持一些复杂的查询,如连接表查询, 否则可能就要在代码中写很多此查询才能做到.

同理execUpdateSQL:

不合理的地方:实际上这里可以查询任何表,破坏了封装性。

(3)接口实现(GenericDao):

createTable: 关键方法在SqlHelper.getCreateTableSQL中,这里通过Java反射机制对采集传进来的Class信息,然后拼接成创建表的SQL语句.

insert | update :关键方法:SqlHelper.parseModelToContentValues,其关键点也是在于利用Java反射机制来把model中的值转化到ContentValue中.

queryByCondition: 也是同理.

insertOrUpdate(T model,String... bindColumnNames):这里关键说一下insertOrUpdate的实现,创建表的时候我们先保存好该表的主键,以后调用该方法时:如果model中的主键值已经存在,则update,反之则insert,以上是不带参数的情况,如果后面带了列名,则根据列名进行联合查询该记录是否存在决定insert Or update。

5、总结:

这个是今年在工作中其中的一点总结,在想方设法提供代码的可重用性是便做了这个东西,但是,时间太赶,所以就本着够用的原则先用着,代码还有很多要完善的地方,但在该基础上再进行构建一些新的支持应该就比较容易了。


摘自: http://my.oschina.net/daxia/blog/193380?p=1

源码路径:http://git.oschina.net/yeguozhong/AndroidGenericDao

  评论这张
 
阅读(274)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016