Android数据库操作通用化
来源:互联网 发布:在淘宝上怎么退货退款 编辑:程序博客网 时间:2024/05/17 03:54
我们热爱的Android中,我们应该如何在Android写出一个通用的数据库增删改查操作,可能也需要借鉴Hibernate的优秀思想。
不过,世间万物都是一步一步进行演化的,我们的代码同样是如此,从不通用到通用,我会通过几篇博客一一向大家展示,但是由于本人经验和学识有限,无法构建出一个完整的开源项目,望大家海涵。有兴趣的可以联系我大家一起尝试做一下(每当你在感叹,如果有这样一个东西就好了的时候,请注意,其实这是你的机会)。
小小说明
整个例子会以一条新闻实体作为基本元素,并贯穿整个例子。新闻实体很简单,我们给它起个名字叫做News
,字段由id
、title
、summary
构成。以下是示例代码:
<code
class
=
"language-java"
hljs=
""
>
public
class
News {
private
int
id;
private
String title;
private
String summary;
// 此处省略get、set方法
}</code>
另外,在SQLite数据库中,存东西绝大多数是String类型的,只有涉及到主键、自增的才会使用int。
最后,想章节名太痛苦,就在网上找了一些有趣的诗词作为章节了,大家按顺序看哦。
一别之后,二地相悬。
实体对象我们已经有了,那么现在就差数据库表了。现在回想一下Android中,数据库表的操作步骤,继承SQLiteOpenHelper,修改一些构造函数,再在onCreate中使用db执行一下建表语句,好像就完成了(数据库版本升级后续再讲)。请看示例代码:
<code
class
=
"language-java"
hljs=
""
>
public
class
DBHelper
extends
SQLiteOpenHelper {
private
static
final
int
VERSION =
1
;
private
static
final
String NAME = bzh.db;
public
DBHelper(Context context) {
super
(context, NAME,
null
, VERSION);
}
// 新闻表:主键+标题+摘要
public
static
final
String TABLE_ID = _id;
public
static
final
String TABLE_NEWS_NAME = news;
public
static
final
String TABLE_NEWS_TITLE = title;
public
static
final
String TABLE_NEWS_SUMMARY = summary;
@Override
public
void
onCreate(SQLiteDatabase db) {
db.execSQL(CREATE TABLE + TABLE_NEWS_NAME + ( +
//
TABLE_ID + integer primary key autoincrement , +
//
TABLE_NEWS_TITLE + varchar(
50
) , +
//
TABLE_NEWS_SUMMARY + varhcar(
200
))
//
);
}
@Override
public
void
onUpgrade(SQLiteDatabase db,
int
oldVersion,
int
newVersion) {
}
}
</code>
仔细看一下代码,其中我们把各个字段和表名都抽取成为了常量字段,这样可以更方便我们写数据库增删改查操作的时候使用。
都说是三四月,谁又知五六年。
现在,实体和表都有了,是时候写增删改查的操作了。既然是增删改查,那么肯定有对应的insert
、delete
、update
、findAll
等操作咯。
而我们作为有经验的开发人员(偷笑),肯定是要面向接口编程咯,那就先写一个NewsDao
吧,整体上很简单,就不写注释了。代码如下:
<code
class
=
"language-java"
hljs=
""
>
public
interface
NewsDao {
long
insert(News news);
int
delete(
int
id);
int
update(News news);
List<news> findAll();
}</news></code>
看起来一切都很顺利,下面是时候写Dao的实现类了,我们就叫做NewsDaoImpl
吧,并实现NewsDao
接口。代码如下:
<code
class
=
"language-java"
hljs=
""
>
public
class
NewsDaoImpl
implements
NewsDao {
private
Context context;
private
DBHelper helper;
private
SQLiteDatabase db;
public
NewsDaoImpl(Context context) {
super
();
this
.context = context;
this
.helper =
new
DBHelper(context);
this
.db = helper.getWritableDatabase();
}
@Override
public
long
insert(News news) {
return
0
;
}
@Override
public
int
delete(
int
id) {
return
0
;
}
@Override
public
int
update(News news) {
return
0
;
}
@Override
public
List<news> findAll() {
return
null
;
}
}</news></code>
貌似架子就是这个样子了,为了执行增删改查等语句,我们需要一个之前写的DBHelper实例,而DBHelper又要求传入Context对象。然后DBHelper又给了我们一个操作数据库SQLiteDatabase实例。
一切很顺利,不过增删改查方法都是空着的,看来接下来只需要填空就好了。
七弦琴无心弹,八行书不可传。
既然是填空,那么我们就只能一个一个来了,太麻烦了(怪不得程序员喜欢偷懒,喵喵!)。
就先从insert
开始吧。
<code
class
=
"language-java"
hljs=
""
>
@Override
public
long
insert(News news) {
ContentValues values =
new
ContentValues();
values.put(DBHelper.TABLE_NEWS_TITLE, news.getTitle());
// ... 此处省略N行代码
return
db.insert(DBHelper.TABLE_NEWS_NAME,
null
, values);
}</code>
当然,我这些只是示例性的代码,你看省略的好多呢,整个insert
的内容一点也不复杂。首先,把字段名和实体字段的对应关系存一个一个入ContentValues
中,然后再执行一下db.insert
,并填入要插入的表名和数据,搜一的一下,就成功了。
接下来是delete
,这么貌似更容易了。在delete
中指定表的名称、过滤条件、以及过滤条件对应的参数,就OK了。
<code
class
=
"language-java"
hljs=
""
>
@Override
public
int
delete(
int
id) {
return
db.delete(DBHelper.TABLE_NEWS_NAME, DBHelper.TABLE_ID + =?,
new
String[] { id + });
}</code>
下面是update
方法。为更新准备一下数据,在update
填入对应的表名、更新值、过滤条件、以及过滤条件对应的参数,这就完成了。当然,为了偷懒,还是省略了一下代码。我保证下个肯定写完整。
<code
class
=
"language-java"
hljs=
""
>
@Override
public
int
update(News news) {
ContentValues values =
new
ContentValues();
values.put(DBHelper.TABLE_NEWS_TITLE, news.getTitle());
// ... 此处省略N行代码
return
db.update(DBHelper.TABLE_NEWS_NAME, values, DBHelper.TABLE_ID + =?,
new
String[] { news.getId() + });
}
</code>
轮到findAll
方法了,这个比较重要,大家仔细听。我们通过db.query()
查询数据,并获取到游标(不要忘记关闭哦),然后就开始移动游标,拿出数据并封装到News
实体中,然后再一个一个加入到List
中。好吧,我承认,这里又偷懒了,嘿嘿。
<code
class
=
"language-java"
hljs=
""
>
@Override
public
List<news> findAll() {
List<news> result =
null
;
// List<m>
Cursor cursor = db.query(DBHelper.TABLE_NEWS_NAME,
null
,
null
,
null
,
null
,
null
,
null
);
if
(cursor !=
null
) {
result =
new
ArrayList<news>();
while
(cursor.moveToNext()) {
News news =
new
News();
// M m = new M();
int
columnIndex = cursor.getColumnIndex(DBHelper.TABLE_NEWS_NAME);
String title = cursor.getString(columnIndex);
news.setTitle(title);
// ... 此处省略N行代码
result.add(news);
}
}
// 关闭游标
cursor.close();
return
result;
}</news></m></news></news></code>
一步一步下来,貌似一个有关News
实体的增删改查的Dao
就出炉了,但是,作为一名程序员,写一个这样子的还是可以承受的,那么万一有更多的User
、AAA
、BBB
、CCC
等等出现怎么办?
难道还要写出来一大堆UserDao
、UserDaoImpl
、AAADao
、AAADaoImpl
等等的一大堆类和方法? 老天,你还是杀了我吧。
那么,问题来了,上述的代码需要解决什么问题,才能变成通用的?
九连环从中折断,十里长亭望眼欲穿!
接下来我们从insert
、delete
、update
、findAll
这些方法中依次分析,看看是哪些问题阻挡了我们通用化的脚步。
insert
中,
<code
class
=
"language-java"
hljs=
""
>ContentValues values =
new
ContentValues();
values.put(DBHelper.TABLE_NEWS_TITLE, news.getTitle());
// ... 此处省略N行代码</code>
如果这些代码能够,以一种“自动”的方式,那么我们的双手就算解放出来一步了,我们需要面对的问题是:如何将实体中的数据,按照对应关系导入到对应的表之中。
<code
class
=
"language-java"
hljs=
""
>
return
db.insert(DBHelper.TABLE_NEWS_NAME,
null
, values);</code>
再看看这句,好像在Java中,写死就等于耦合、等于不方便。而DBHelper.TABLE_NEWS_NAME
好像也固定在语句之中了,看来这句代码也阻挡了我们解放双手的步伐,嘿嘿,又出来一个。我们需要面对的问题是:如何获取表名。
这个方法是没有了,接下来看看delete
,
<code
class
=
"language-java"
hljs=
""
>
return
db.delete(DBHelper.TABLE_NEWS_NAME, DBHelper.TABLE_ID + =?,
new
String[] { id + });</code>
其中的DBHelper.TABLE_NEWS_NAME
我们已经记录下来了,那么,后面的DBHelper.TABLE_ID
又是怎么回事? 哦,原来是主键,也是固定写死的。看来这也是我们面对的问题:明确实体中的主键是谁,并获取到主键中封装的值。
再看看update
方法,仔细瞅瞅~ 好像没有耶!那么就继续下一个findAll
方法。
<code
class
=
"language-java"
hljs=
""
>News news =
new
News();
// M m = new M();
int
columnIndex = cursor.getColumnIndex(DBHelper.TABLE_NEWS_NAME);
String title = cursor.getString(columnIndex);
news.setTitle(title);
// ... 此处省略N行代码www.2cto.com</code>
这里是将游标中的数据取出来,并放入到对应的实体属性中去,这里最容易出现错误、并且也是写死的。看来这里也是问题之一:将数据库表中列的数据,按照对应关系导入到实体之中。
分析完后,我们已经可以总结出一二三四五六七八条了。哈哈。(貌似没有这么多。)
披荆斩棘
需要解决什么问题,才能变成通用的? ① 表名的获取 ② 如何将实体中的数据,按照对应关系导入到对应的表之中。 ③ 明确实体中的主键是谁,并获取到主键中封装的值。 ④ 搞定实体对象的创建 ⑤ 将数据库表中列的数据,按照对应关系导入到实体之中。以上就是全部问题所在了,如果能够搞定这些,在Android中的数据库通用操作也就应运而生了。
- Android数据库操作通用化
- 如何将Android数据库操作通用化(一)
- 如何将Android数据库操作通用化(二)
- 如何将Android数据库操作通用化(三)
- 如何将Android数据库操作通用化(四)
- 如何将Android数据库操作通用化(一)
- 如何将Android数据库操作通用化(二)
- 数据库操作通用代码!
- 数据库通用操作
- 通用数据库操作BEAN
- Android sqlite数据库操作通用框架AHibernate(1)
- Android sqlite数据库操作通用框架AHibernate(二)-CRUD ...
- android通用文件操作
- C# 通用数据库类操作
- Hibernate通用数据库操作代码
- Hibernate通用数据库操作代码
- C#数据库操作通用类
- JDBC连接数据库通用操作
- PXE启动芯片出错代码表初始化/引导/载入Bootstrap错误代码
- JAVA中的Random()函数
- handler 类型在转换异常
- Linux无线网络操作相关命令
- Hibernate的List映射
- Android数据库操作通用化
- 杭电2067小兔的棋盘
- NYOJ 770 仿射密码 (字符串&数学)
- 欢迎使用CSDN-markdown编辑器
- hdoj1086You can Solve a Geometry Problem too【线段相交判断】
- 使用CryptoAPI获取证书扩展属性之三:“颁发机构密钥标识”和"使用者密钥标识"
- Android6.0新特性
- python-time
- 启动oracle