转载部分来自:http://blog.csdn.net/zuolongsnail/article/details/6529096,http://fine36.blog.163.com/blog/static/189251005201183053216297/


Android中的数据库存储是直接使用了SQLite。在Android应用中创建数据库后数据库文件是存储在/data/ data/应用包名/databases/下。

在Android中使用到SQLite会涉及到以下三个类或接口:
1.SQLiteOpenHelper

*SQLiteOpenHelper 构造方法,一般传递一个要创建的数据库名称name参数
*onCreate 创建数据库时调用(创建所有表的操作)
*onUpgrade 版本更新时调用
*getReadableDatabase 创建或打开一个只读数据库
*getWritableDatabase 创建或打开一个读写数据库

2.SQLiteDatabase
*openOrCreateDatabase 打开或者创建数据库
*insert 添加一条记录
*delete 删除一条记录
*query 查询记录
*update 更新记录
*execSQL 执行一条SQL语句
*close 关闭数据库

3.Cursor
*getCount 总记录条数
*isFirst 判断是否第一条记录
*isLast 判断是否最后一条记录
*moveToFirst 移动到第一条记录
*moveToLast 移动到最后一条记录
*move 移动到指定记录
*moveToNext 移动到下一条记录
*moveToPrevious 移动到上一条记录
*getColumnIndexOrThrow根据列名称获得列索引
*getInt 获得指定列索引的int类型值
*getString 获得指定列索引的String类型值
注:某些方法是有重载的,可以结合docs熟悉下。

android.database.sqlite.SQLiteDatabaseAndroid SDK中操作数据库的核心类之一。使用SQLiteDatabase可以打开数据库,也可以对数据库进行操作。然而,为了数据库升级的需要以及使用更方便,往往使用SQLiteOpenHelper的子类来完成创建、打开数据库及各种数据库的操作。
SQLiteOpenHelper是一个抽象类,在该类中有如下两个抽象方法,因此,SQLiteOpenHelper的子类必须实现这两个方法。
public abstract void onCreate(SQLiteDatabase db);
public abstract void onUpgrade(SQLiteDatabase db,int oldVersion, int newVersion);

onCreate()调用:
SQLiteOpenHelper会自动检测数据库文件是否存在。如果数据库文件存在,会打开这个数据库。如果数据库文件不存在的时候,SQLiteOpenHelper首先会创建一个数据库文件,然后打开这个数据库,最后会调用onCreate方法。因此,onCreate方法一般被用来在新创建的数据库中建立表、视图等数据库组件。也就是说,onCreate方法在数据库文件第一次被创建时调用。

onUpgrade()调用:

SQLiteOpenHelper类的构造方法:
public SQLiteOpenHelper(Context context, Stringname, CursorFactory factory, int version);
参数意义:

name参数表示数据库文件名(不包含文件路径),SQLiteOpenHelper会根据这个文件名创建数据库文件。

version表示数据库的版本号。

如果当前传递的数据库版本号比上次创建或升级的数据库版本号高。SQLiteOpenHelper就会调用onUpgrade方法。也就是说,当数据库第1次创建时会有一个初始的版本号。当需要对数据库中表、视图等组件升级时可以增大版本号。这时SQLiteOpenHelper会调用onUpgrade方法。当调用完onUpgrade方法后,系统会更新数据库的版本号。这个当前的版本号就是通过SQLiteOpenHelper类的最后一个参数version传入SQLiteOpenHelper对象的。

因此,在onUpgrade方法中一般会首先删除要升级的表、视图等组件,再重新创建它们。

(举例:如果版本1创建了表a、表b,后来版本升级后,版本2里面有表a,同时多了表c,没有了之前版本的表b,用户分为两种:

一种是第一次使用的是版本2,不是直接升级软件的用户,因为是第一次进入,发现没有数据库,所以就在SQLiteOpenHelper构造器里面创建数据库,然后自动的调用onCreate方法创建这个版本所需要的表。

一种是使用了版本1的用户,他直接升级软件,这个时候,系统识别已经创建了数据库,所以不会调用onCreate(),因为版本有改变,会调用onUpgrade方法,这个方法里面就要去删除表b的操作,因为升级版本的用户,系统不会自动的调用onCreate方法,所以可能会错过表c,所以在onUpgrade方法里面手动的调用onCreate方法去创建表(onCreate里面创表的语句一定要用create table if not exists xxx,如果不存在就创建,存在直接用。避免重复的建表)



下面贴上数据库操作的代码,完整代码下载地址:android_sqlite.rar

1.创建数据库只要自定义一个类继承SQLiteOpenHelper即可。在SQLiteOpenHelper的子类中至少需要实现三个方法:
*构造方法,调用父类SQLiteOpenHelper的构造函数。需要四个参数:上下文环境(例如一个Activity);数据库名称;一个可选的游标工
厂(通常是null);一个正在使用的数据库版本。
*onCreate方法,需要一个SQLiteDatabase对象作为参数,根据需要对这个对象填充表和初始化数据。
*onUpgrade方法,需要三个参数:一个SQLiteDatabase对象,一个旧的版本号和一个新的版本号。


(为了数据库的多次使用,同时避免错误,一个工程的数据库应该独立在一个包里面,里面包含3个java文件:

一个是继承SQLiteOpenHelper的子类(负责创建数据库和各种表视图等,同时解决版本升级的问题),

一个是数据库操作的类(负责数据库的增删改查),一个专门存储数据库的常量的java类(SQL语句不小心就出个小错,所以我们写成常量,要用的时候直接调用,避免他人使用这些常量的时候出错,也便于我们统一修改。)

[java] view plain copy
  1. /**
  2. *数据库操作助手类
  3. *
  4. *@authorzuolongsnail
  5. */
  6. publicclassAndroidSQLiteOpenHelperextendsSQLiteOpenHelper{
  7. //数据库名称
  8. publicstaticfinalStringDBNAME="android.db";
  9. //数据库版本
  10. publicstaticfinalintVERSION=2;
  11. //建表语句,大小写不敏感
  12. privatestaticfinalStringCREATETABLE="createtable"
  13. +Person.TABLENAME
  14. +"(idstring,namestring,genderint,ageint)";
  15. publicAndroidSQLiteOpenHelper(Contextcontext){
  16. super(context,DBNAME,null,VERSION);
  17. }
  18. //创建表
  19. @Override
  20. publicvoidonCreate(SQLiteDatabasedb){
  21. db.execSQL(CREATETABLE);
  22. }
  23. //更新表
  24. @Override
  25. publicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){
  26. this.deleteDB(db);
  27. this.onCreate(db);
  28. }
  29. //删除表
  30. privatevoiddeleteDB(SQLiteDatabasedb){
  31. db.execSQL("droptableifexists"+Person.TABLENAME);
  32. }
  33. }

2.对数据库表进行操作,包括添加、删除、修改和查询。(下面的代码使用的是第一种方法)
有两种方法可以对数据库表进行操作:使用execSQL方法执行SQL语句;使用insert、delete、update和query方法,把SQL语句的一部分
作为参数。(下面的代码使用的是第一种方法)
注:查询数据库时执行SQL语句是使用SQLiteDatabase的rawQuery方法而不是execSQL。

[java] view plain copy
  1. /**
  2. *数据库管理类
  3. *
  4. *@authorzuolongsnail
  5. *
  6. */
  7. publicclassDatabaseManager{
  8. privateAndroidSQLiteOpenHelperdbHelper;
  9. publicDatabaseManager(Contextcontext){
  10. dbHelper=newAndroidSQLiteOpenHelper(context);
  11. }
  12. //插入记录
  13. publicintinsert(Personperson){
  14. Log.e("SQLite","----insert----");
  15. SQLiteDatabasedb=dbHelper.getWritableDatabase();
  16. db.beginTransaction();
  17. try{
  18. db.execSQL("insertinto"+Person.TABLENAME
  19. +"values(?,?,?,?)",newObject[]{person.id,
  20. person.name,person.gender,person.age});
  21. db.setTransactionSuccessful();
  22. }catch(Exceptione){
  23. return0;
  24. }finally{
  25. db.endTransaction();
  26. }
  27. db.close();
  28. return1;
  29. }
  30. //删除记录
  31. publicintdelete(Personperson){
  32. Log.e("SQLite","----delete----");
  33. SQLiteDatabasedb=dbHelper.getWritableDatabase();
  34. db.beginTransaction();
  35. try{
  36. db.execSQL("deletefrom"+Person.TABLENAME+"whereid=?",
  37. newObject[]{person.id});
  38. db.setTransactionSuccessful();
  39. }catch(Exceptione){
  40. return0;
  41. }finally{
  42. db.endTransaction();
  43. }
  44. db.close();
  45. return1;
  46. }
  47. //更新记录
  48. publicintupdate(Personperson){
  49. Log.e("SQLite","----update----");
  50. SQLiteDatabasedb=dbHelper.getWritableDatabase();
  51. db.beginTransaction();
  52. try{
  53. db.execSQL("update"+Person.TABLENAME
  54. +"setname=?,gender=?,age=?whereid=?",newObject[]{
  55. person.name,person.gender,person.age,person.id});
  56. db.setTransactionSuccessful();
  57. }catch(Exceptione){
  58. return0;
  59. }finally{
  60. db.endTransaction();
  61. }
  62. db.close();
  63. return1;
  64. }
  65. //查询记录
  66. publicArrayList<Person>query(Stringid){
  67. Log.e("SQLite","----query----");
  68. SQLiteDatabasedb=dbHelper.getReadableDatabase();
  69. Cursorcursor;
  70. Personperson;
  71. ArrayList<Person>list=newArrayList<Person>();
  72. //若fileId为null或""则查询所有记录
  73. if(id==null||id.equals("")){
  74. cursor=db.rawQuery("select*from"+Person.TABLENAME,null);
  75. }else{
  76. cursor=db.rawQuery("select*from"+Person.TABLENAME
  77. +"whereid=?",newString[]{id});
  78. }
  79. while(cursor.moveToNext()){
  80. person=newPerson();
  81. person.id=cursor.getString(cursor.getColumnIndex("id"));
  82. person.name=cursor.getString(cursor.getColumnIndex("name"));
  83. person.gender=cursor.getString(cursor.getColumnIndex("gender"));
  84. person.age=cursor.getInt(cursor.getColumnIndex("age"));
  85. Log.e("SQLite",person.toString());
  86. list.add(person);
  87. }
  88. cursor.close();
  89. db.close();
  90. if(list.size()==0){
  91. Log.e("SQLite","****表中无数据****");
  92. }
  93. returnlist;
  94. }
  95. }

3、对数据库需要的常量专门定义一个类管理,比如:DBConfig.java(举例说明而已,与上面的不是代码不是一个人的)


/** * 数据库的工具类 * 里面封装了很多常量,便于用数据库的时候直接访问 * @author Administrator * */public class DBConfig {/**数据库名*/final static String DB_NAME ="UserDatabase.db";/**创建表语句的头部*/static final String CREAT_TABLE_HEAD="create table if not exists ";/**创建表语句的主件自增*/static final String PRIMARY_KEY=" integer primary key autoincrement,";/**版本号*/final static  int VERSION=1;/**表名称*/static final String TB_USER="user";/**字段名id*/static final String C_ID="id";/**字段名name*/static final String C_NAME="name";/**字段名tel*/static final String C_TEL="tel";}

 有了这个类之后,需要创建表的语句:  

sql语句:create table if not exists tb_note(id integer primary key autoincrement,title verchar(30),content text ,time verchar(30))

下面为调用了DBConfig.java类的sql语句,这样可以避免书写出现的错误

static final String CREAT_TABLE_USER = DBConfig.CREAT_TABLE_HEAD+ DBConfig.TB_USER+"(" +DBConfig.C_ID+DBConfig.PRIMARY_KEY+DBConfig.C_NAME+" verchar(30)," +DBConfig.C_TEL+" verchar(30))";

有了常量之后的数据库操作类可以这样写:

/** * 数据库的工具类 负责表的增删改查 *  * @author Administrator *  */public class DBOperator {SQLiteDatabase mySql;MyDBHelper helper;public DBOperator(Context context) {helper = new MyDBHelper(context);mySql = helper.getReadableDatabase();}/** * 插入数据 * @param user * @return  */public long addUser(User user) {if(user!=null){return mySql.insert(DBConfig.TB_USER, null, buildValues(user));}return 0;}private ContentValues buildValues(User user){ContentValues values=new ContentValues();values.put(DBConfig.C_NAME, user.getName());values.put(DBConfig.C_TEL, user.getTel());return values;}/** * 删除数据 * @param id * @return  */public int deleteUserById(int id){//mySql.delete("tb_note", "time=?", new String[]{time});return mySql.delete(DBConfig.TB_USER, DBConfig.C_ID+"="+id, null);}/** * 更新数据 * @param user * @return  */public int changeUser(User user){if(user==null || user.getId()==0){//如果传进来的user是刚new之后的user那user不为null,但是id等int型默认为0return 0;}else{return mySql.update(DBConfig.TB_USER, buildValues(user), DBConfig.C_ID+"="+user.getId(), null);}}/** * 通过id查询指定数据 * @param id * @return */public User queryById(int id){//sql语句:mySql.rawQuery("select * from "+DBConfig.TB_USER+" where "+DBConfig.C_ID+"="+id, null);Cursor cursor=mySql.query(DBConfig.TB_USER, null, DBConfig.C_ID+"="+id, null, null, null, null);User user=null;if(cursor.moveToNext()){user=cursorToGetUser(cursor);}cursor.close();return user;}/** * 查询表中所有东西 * @return */public  List<User> queryUserAll(){Cursor cursor=mySql.rawQuery("select * from "+DBConfig.TB_USER, null);List<User> list=new ArrayList<User>();while(cursor.moveToNext()){User user=cursorToGetUser(cursor);list.add(user);user=null;}cursor.close();return list;}private User cursorToGetUser(Cursor cursor){User user=new User();user.setId(cursor.getInt(cursor.getColumnIndex(DBConfig.C_ID)));user.setName(cursor.getString(cursor.getColumnIndex(DBConfig.C_NAME)));user.setTel(cursor.getString(cursor.getColumnIndex(DBConfig.C_TEL)));return user;}/** * 关闭数据库 */public void dbClose(){if(mySql!=null){mySql.close();}}}

SQLiteDatabase的使用(建议使用上面的SQLiteOpenHelper


private SQLiteDatabase mySql;
<span style="font-size: 12px;"><span style="white-space: pre;"></span>/**</span>
 * 创建数据库 */private void createDataBase() {if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {File file = Environment.getExternalStorageDirectory();File newFile = new File(file, "noteBook.db");mySql=SQLiteDatabase.openOrCreateDatabase(newFile, null);String sql="create table if not exists tb_note(id integer primary key autoincrement,title verchar(30),content text ,time verchar(30))";mySql.execSQL(sql);}}

删除数据:

final String time=note.getTime();mySql.delete("tb_note", "time=?", new String[]{time});

查询表中所有数据:

<span style="white-space:pre"></span>/** * 获取数据 * @return  */private List<NoteBook> queryDatabase() {list=new ArrayList<NoteBook>();Cursor cursor=mySql.query("tb_note", null, null, null, null, null, null);int count=cursor.getCount();//得到行数if(count>0){while(cursor.moveToNext()){String title=cursor.getString(cursor.getColumnIndex("title"));String time=cursor.getString(cursor.getColumnIndex("time"));//取数据存入note对象中NoteBook note=new NoteBook();note.setTitle(title);note.setTime(time);//把对象存listlist.add(note);note=null;//方便回收}cursor.close();}return list;}

cursor游标的使用 :转载:http://blog.sina.com.cn/s/blog_618199e60101fskp.html

在你理解和使用 Android Cursor 的时候你必须先知道关于 Cursor 的几件事情:

Cursor 是每行的集合。使用 moveToFirst() 定位第一行。你必须知道每一列的名称。你必须知道每一列的数据类型。Cursor 是一个随机的数据源。所有的数据都是通过下标取得。
关于 Cursor 的重要方法:

·close()——关闭游标,释放资源
·copyStringToBuffer(int columnIndex, CharArrayBuffer buffer)——在缓冲区中检索请求的列的文本,将将其存储
·getColumnCount()——返回所有列的总数
·getColumnIndex(String columnName)——返回指定名称所在的列,如果不存在返回-1
·getColumnIndexOrThrow(String columnName)——从零开始返回指定列名称,如果不存在将抛出IllegalArgumentException异常。
·getColumnName(int columnIndex)——从给定的索引返回列名
·getColumnNames()——返回一个字符串数组的列名
·getCount()——返回Cursor 中的行数
·moveToFirst()——移动光标到第一行
·moveToLast()——移动光标到最后一行
·moveToNext()——移动光标到下一行
·moveToPosition(int position)——移动光标到一个绝对的位置
·moveToPrevious()——移动光标到上一行

下面来看看一小段代码:

if (cur.moveToFirst() == false){ //为空的Cursor
return;
}

访问 Cursor 的下标获得其中的数据

int nameColumnIndex = cur.getColumnIndex(People.NAME);
String name = cur.getString(nameColumnIndex);
现在让我们看看如何循环 Cursor 取出我们需要的数据

while(cur.moveToNext()) {
//光标移动成功

String email =cursor.getString(cursor.getColumnIndex(RuiXin.EMAIL));

startManagingCursor(cursor);//查找后关闭游标
//把数据取出
}


当cur.moveToNext() 为假时将跳出循环,即 Cursor 数据循环完毕。

如果你喜欢用 for 循环而不想用While 循环可以使用Google 提供的几下方法:

·isBeforeFirst()——返回游标是否指向之前第一行的位置
·isAfterLast()——返回游标是否指向第最后一行的位置
·isClosed()——如果返回 true 即表示该游戏标己关闭
有了以上的方法,可以如此取出数据

for(cur.moveToFirst();!cur.isAfterLast();cur.moveToNext())
{
int nameColumn = cur.getColumnIndex(People.NAME);
int phoneColumn = cur.getColumnIndex(People.NUMBER);
String name = cur.getString(nameColumn);
String phoneNumber = cur.getString(phoneColumn);
}

Tip:在Android 查询数据是通过Cursor 类来实现的。当我们使用 SQLiteDatabase.query()方法时,就会得到Cursor对象, Cursor所指向的就是每一条数据。

Cursor 位于 android.database.Cursor类,可见出它的设计是基于数据库服务产生的。


另:Activity.startManagingCursor方法:

将获得的Cursor对象交与Activity管理,这样Cursor对象的生命周期便能与当前的Activity自动同步,省去了自己对Cursor的管理。

1.这个方法使用的前提是:游标结果集里有很多的数据记录。

所以,在使用之前,先对Cursor是否为null进行判断,如果Cursor != null,再使用此方法 2.如果使用这个方法,最后也要用stopManagingCursor()来把它停止掉,以免出现错误。 3.使用这个方法的目的是把获取的Cursor对象交给Activity管理,这样Cursor的生命周期便能和Activity自动同步,省去自己手动管理。

手动处理cursor关闭:cursor.close();

更多相关文章

  1. “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
  2. Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
  3. 不吹不黑!GitHub 上帮助人们学习编码的 12 个资源,错过血亏...
  4. android 常用到的 listview ,scrollview 等上拉刷新
  5. Android基础 : Android(安卓)ContentProvider
  6. Android(安卓)工程编译 Unsupported major.minor version 51.0
  7. [Android]使用permission保护数据
  8. 关于android的反射机制的用法
  9. Android快速实现断点续传的方法

随机推荐

  1. Android好的文章,持续更新
  2. Android下数据库的解析
  3. android 打包 生成apk 出现的问题 javasc
  4. android选择视频文件上传到后台服务器
  5. Android(安卓)开发 设置banner圆角,滑动时
  6. Android(安卓)ListView 实现 GridView 用
  7. Android(安卓)中文API(86)――ResourceCurs
  8. Android,一个函数实现支付宝...
  9. Android(安卓)Screen Monitor
  10. 面试 | Android(安卓)View、布局、动画、