android中的数据存取-方式三:SQLite

简介:

1.Android中通过SQLite数据库引擎来实现结构化数据存储。SQLite是一个嵌入式数据库引擎,针对内存等资源有限的设备,提供的是一种高效的数据库引擎。
2.Android提供了创建和使用SQLite数据库的API。SQLiteDatabase代表一个数据库对象,提供了操作数据库的一些方法,另外还有一个SQLiteOpenHelper工具类提供更简洁的功能。
3. SQLiteOpenHelper是SQliteDatabase的一个帮助类,用来管理数据库的创建和版本更新。一般用法是定义一个类继承之,并实现两个抽象方法onCreate(SQLiteDatabase db)和onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion)类创建和跟新数据库。

 

Android中操作数据库首先要通过一个 类:android.database.sqlite.SQLiteOpenHelper。它封装了如何打开一个数据库,其中当然也包含如果数据库不存在 就创建这样的逻辑。看一个例子:

 
pubilc class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "com.roiding.simple.note";
private static final int DATABASE_VERSION = 1;
private static final String NOTES_TABLE_NAME = "notes";

DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + NOTES_TABLE_NAME
+ " (id integer primary key autoincrement, name text);");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS notes");
onCreate(db);
}
}

这里面,如下的语句需要解释:

  • super(context, DATABASE_NAME, null, DATABASE_VERSION)
    数据库连接的初始化,中间的那个null,是一个CursorFactory参数,没有仔细研究这个参数,暂时置空吧。
  • public void onCreate(SQLiteDatabase db)
    这里面的onCreate是指数据库onCreate时,而不是DatabaseHelper的onCreate。也就是说,如果已经指定 database已经存在,那么在重新运行程序的时候,就不会执行这个方法了。要不然,岂不是每次重新启动程序都要重新创建一次数据库了!在这个方法中,完成了数据库的创建工作。也就是那个execSQL()方法。
  • public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
    在程序的开发维护过程中,数据库的结构可能会有变化,那么这个方法就有用处了。在DatabaseHelper这个对象一创建时,就已经把参数 DATABASE_VERSION传入,这样,如果Android发现此版本与现有版本不一致,就会调用这个onUpgrate方法。于是,可以在这里面实现一些数据的upgrade工作,比如说创建一个临时表,将数据由临时表中转到新的表结构中。需要注意的是,这里面的onUpgrade是在版本不一致时调用,也就是说不管当前需要的版本高于现有版本还是低于现有版本,都会出发这个方法,类似的这种情况,就需要对oldVersion和 newVersion进行判断之后再决定使用什么策略来更新数据。

在Android中,数据库存放在 /data/data/PACKAGE_NAME/databases 目录下。

接下来就可以使用这个Helper来操作数据库了,操作数据库也就无非是增、删、改、查。先看一个增的例子:

 

 

public static void insert(Context context, String s) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);

String table = "notes";
String nullColumnHack = "id";

ContentValues values = new ContentValues();
values.put("name", "www.roiding.com");

long id = mOpenHelper.getReadableDatabase().insert(table,
nullColumnHack, values);

mOpenHelper.getReadableDatabase().close();
}
  • DatabaseHelper mOpenHelper = new DatabaseHelper(context);
    如果和JDBC例子的话,这一步貌似就像是获得了一个Statement,用它就可以操作数据库了。
  • ContentValues values = new ContentValues();
    Android在向数据库中插入数据的时候,要求数据存放到ContentValues中,这里面的ContentValues其实就是一个 Map,Key值是字段名称,Value值是字段的值。这样,也许你会发现一个问题,那数据类型怎么办?其实在SQLite数据库中就是没有数据类型的, 一切都是字符串。
  • mOpenHelper.getReadableDatabase().insert(table,nullColumnHack, values);
    将数据入库,注意这里面有一个nullColumnHack,看文档是和所有字段都是空的记录有关系,我没有去实验他具体的效果,只是随便给他一个字段名称。

再看一个查的例子:

public static void select(Context context) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);

String table = "notes";
String[] columns = new String[] { "id", "name" };
String selection = "id>? and name<>?";
String[] selectionArgs = new String[] { "0", "roiding.com" };
String groupBy = null;
String having = null;
String orderBy = "id desc";
String limit = "1";

Cursor c = mOpenHelper.getReadableDatabase().query(table,
columns, selection, selectionArgs, groupBy, having, orderBy, limit);

c.moveToFirst();
for (int i = 0; i < c.getCount(); i++) {
String s = c.getString(1);
c.moveToNext();
}
c.close();
mOpenHelper.getReadableDatabase().close();
}
  • DatabaseHelper mOpenHelper = new DatabaseHelper(context);
    于前文中的相同
  • mOpenHelper.getReadableDatabase().query();
    通过mOpenHelper.getReadableDatabase(),会得到一个SQLiteDatabase类型的只读的数据库连接,在这里直接调用了他的query方法。这个query方法相对复杂,因为他将一个完整的SQL语句拆成了若干个部分:

     

    • table:表名。相当于SQL的from后面的部分。那如果是多表联合查询怎么办?那就用逗号将两个表名分开,拼成一个字符串作为table的值。
    • columns:要查询出来的列名。相当于SQL的select后面的部分。
    • selection:查询条件,相当于SQL的where后面的部分,在这个语句中允许使用“?”,也就是说这个用法和JDBC中的PreparedStatement的用法相似。
    • selectionArgs:对应于selection的值,selection有几个问号,这里就得用几个值。两者必须一致,否则就会有异常。
    • groupBy:相当于SQL的group by后面的部分
    • having:相当于SQL的having后面的部分
    • orderBy:相当于SQL的order by后面的部分,如果是倒序,或者是联合排序,可以写成类似这样:String orderBy = “id desc, name”;
    • limit:指定结果集的大小,它和Mysql的limit用法不太一样,mysql可以指定从多少行开始之后取多少条,例如“limit 100,10”,但是这里只支持一个数值。
  • c.moveToFirst();
    这一句也比较重要,如果读取数据之前,没有这一句,会有异常。
  • c.getString(1);
    与JDBC一致了,Android不支持按字段名来取值,只能用序号。

再看一个删除和修改的例子:

 
public static void delete(Context context) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);

String table = "notes";
String selection = "id>? and name<>?";
String[] selectionArgs = new String[] { "0", "roiding.com" };
String whereClause = selection;
String[] whereArgs = selectionArgs;

mOpenHelper.getWritableDatabase().delete(table, whereClause, whereArgs);
mOpenHelper.getWritableDatabase().close();
}

有了上面的基础这里就容易理解了,这里的whereClause相当于前面的selection,whereArgs相当于前面的selectionArgs。

 

 

public static void update(Context context) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);

String table = "notes";
String selection = "id>? and name<>?";
String[] selectionArgs = new String[] { "0", "roiding.com" };
String whereClause = selection;
String[] whereArgs = selectionArgs;

ContentValues values = new ContentValues();
values.put("name", "www.roiding.com");

mOpenHelper.getWritableDatabase().update(table, values,
whereClause, whereArgs);
mOpenHelper.getWritableDatabase().close();
}

这个update的用法,综合select和delete就可以理解。

注意:

  • Cursor和Databases要及时关闭,不然也会有异常。
  • getWritableDatabase()和getReadableDatabase()在当前的Android版本中貌似可以通用,像上面的insert,用的就是getReadableDatabase。

在真实的应用中,会对上面这些基本操作做更高一级的抽象和封装,使之更容易使用。在select时,除了用上述的方法,将分段的SQL语句传进去之外,Android还支持一种方法:使用SQLiteQueryBuilder。如果使用的是上述的分段SQL语句的方法,在Android的内部实现中,也是先将分段的SQL使用SQLiteQueryBuilder的静态方法来生成一个真正的SQL的,而且,我没有看出来使用SQLiteQueryBuilder的优势。

 

/Chapter09_Data_03/src/com/amaker/test/MainActivity.java

 

 
  1. 代码  
  2.  
  3. package com.amaker.test;  
  4.  
  5. import android.app.Activity;  
  6. import android.content.ContentValues;  
  7. import android.database.Cursor;  
  8. import android.database.sqlite.SQLiteDatabase;  
  9. import android.os.Bundle;  
  10.  
  11. public class MainActivity extends Activity {  
  12.     @Override  
  13.     public void onCreate(Bundle savedInstanceState) {  
  14.         super.onCreate(savedInstanceState);  
  15.         setContentView(R.layout.main);  
  16.           
  17.         SQLiteDatabase db = createDatabase();  
  18.         //createTable(db);  
  19.         //insert(db);  
  20.         //insert2(db);  
  21.         //update(db);  
  22.        // update2(db);  
  23.        // delete(db);  
  24.         delete2(db);  
  25.         query(db);  
  26.         db.close();  
  27.           
  28.     }  
  29.     // 创建数据库,注意这里要指定全路径  
  30.     private SQLiteDatabase createDatabase(){  
  31.         return SQLiteDatabase.openOrCreateDatabase("/data/data/com.amaker.test/databases/temp2.db", null);  
  32.     }  
  33.     // 创建表  
  34.     private void createTable(SQLiteDatabase db){  
  35.         String sql = " create table UserTbl(_id integer primary key autoincrement,username text,password text)";  
  36.         db.execSQL(sql);  
  37.     }  
  38.     // 插入数据  
  39.     private void insert(SQLiteDatabase db){  
  40.         String sql = " insert into UserTbl(username,password) values('amaker','123') ";  
  41.         db.execSQL(sql);  
  42.     }  
  43.     // 插入2   
  44.    private void insert2(SQLiteDatabase db){  
  45.        ContentValues cv =new ContentValues();  
  46.        cv.put("username","ghz");  
  47.        cv.put("password", "456");  
  48.        db.insert("UserTbl", null, cv);  
  49.    }  
  50.     // 查询  
  51.     private void query(SQLiteDatabase db){  
  52.         Cursor c = db.query("UserTbl", null, null, null, null, null, null);  
  53.         if(c.moveToFirst()){  
  54.             for (int i = 0; i < c.getCount(); i++) {  
  55.                 c.move(i);  
  56.                 int id = c.getInt(0);  
  57.                 String username = c.getString(1);  
  58.                 String password = c.getString(2);  
  59.                 System.out.println(id+":"+username+":"+password);  
  60.             }  
  61.         }  
  62.     }  
  63.     // 修改  
  64.     private void update(SQLiteDatabase db){  
  65.         String sql = " update UserTbl set password=888 where _id=1 ";  
  66.         db.execSQL(sql);  
  67.     }  
  68.     // 修改2  
  69.     private void update2(SQLiteDatabase db){  
  70.         ContentValues values = new ContentValues();  
  71.         values.put("password", "999");  
  72.         String whereClause = "_id=?";  
  73.         String[] whereArgs = {String.valueOf(1)};  
  74.         db.update("UserTbl", values, whereClause, whereArgs);  
  75.     }  
  76.       
  77.     // 删除  
  78.     private void delete(SQLiteDatabase db){  
  79.         String sql = " delete from UserTbl where _id=2 ";  
  80.         db.execSQL(sql);  
  81.     }  
  82.     // 删除2  
  83.     private void delete2(SQLiteDatabase db){  
  84.         String whereClause = "_id=?";  
  85.         String[] whereArgs = {String.valueOf(1)};  
  86.         db.delete("UserTbl", whereClause, whereArgs);  
  87.     }  
  88.       
  89.       

/Chapter09_Data_03/res/layout/main.xml

 

 
  1. 代码  
  2.  
  3. <?xml version="1.0" encoding="utf-8"?> 
  4. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  5.     android:orientation="vertical" 
  6.     android:layout_width="fill_parent" 
  7.     android:layout_height="fill_parent" 
  8.     > 
  9. <TextView    
  10.     android:layout_width="fill_parent"   
  11.     android:layout_height="wrap_content"   
  12.     android:text="@string/hello" 
  13.     /> 
  14. </LinearLayout> 

/Chapter09_Data_03/AndroidManifest.xml

 

 
  1. 代码  
  2.  
  3. <?xml version="1.0" encoding="utf-8"?> 
  4. <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
  5.       package="com.amaker.test" 
  6.       android:versionCode="1" 
  7.       android:versionName="1.0"> 
  8.     <application android:icon="@drawable/icon" android:label="@string/app_name"> 
  9.         <activity android:name=".MainActivity" 
  10.                   android:label="@string/app_name"> 
  11.             <intent-filter> 
  12.                 <action android:name="android.intent.action.MAIN" /> 
  13.                 <category android:name="android.intent.category.LAUNCHER" /> 
  14.             </intent-filter> 
  15.         </activity> 
  16.  
  17.     </application> 
  18.     <uses-sdk android:minSdkVersion="3" /> 
  19.  
  20. </manifest> 

 


本文转自linzheng 51CTO博客,原文链接:http://blog.51cto.com/linzheng/1079363


相关文章
|
3月前
|
安全 API Android开发
Android网络和数据交互: 解释Retrofit库的作用。
Android网络和数据交互: 解释Retrofit库的作用。
39 0
|
3月前
|
存储 数据库连接 数据库
Android数据存储:解释SQLite数据库在Android中的使用。
Android数据存储:解释SQLite数据库在Android中的使用。
42 0
|
4月前
|
XML 物联网 API
Android Ble蓝牙App(五)数据操作
Android Ble蓝牙App(五)数据操作
|
4月前
|
数据库 Android开发 开发者
Android Studio入门之内容共享ContentProvider讲解以及实现共享数据实战(附源码 超详细必看)
Android Studio入门之内容共享ContentProvider讲解以及实现共享数据实战(附源码 超详细必看)
41 0
|
9天前
|
Android开发 开发者
Android网络和数据交互: 请解释Android中的AsyncTask的作用。
Android&#39;s AsyncTask simplifies asynchronous tasks for brief background work, bridging UI and worker threads. It involves execute() for starting tasks, doInBackground() for background execution, publishProgress() for progress updates, and onPostExecute() for returning results to the main thread.
10 0
|
9天前
|
网络协议 安全 API
Android网络和数据交互: 什么是HTTP和HTTPS?在Android中如何进行网络请求?
HTTP和HTTPS是网络数据传输协议,HTTP基于TCP/IP,简单快速,HTTPS则是加密的HTTP,确保数据安全。在Android中,过去常用HttpURLConnection和HttpClient,但HttpClient自Android 6.0起被移除。现在推荐使用支持TLS、流式上传下载、超时配置等特性的HttpsURLConnection进行网络请求。
9 0
|
23天前
|
XML Java Android开发
Android每点击一次按钮就添加一条数据
Android每点击一次按钮就添加一条数据
23 1
|
1月前
|
存储 Android开发 C++
【Android 从入门到出门】第五章:使用DataStore存储数据和测试
【Android 从入门到出门】第五章:使用DataStore存储数据和测试
34 3
|
2月前
|
JavaScript Java 数据安全/隐私保护
安卓逆向 -- POST数据解密
安卓逆向 -- POST数据解密
27 2
|
3月前
|
编解码 测试技术 开发工具
如何实现Android视音频数据对接到GB28181平台(SmartGBD)
如何实现Android视音频数据对接到GB28181平台(SmartGBD)