前几天学习了Android中的数据存储,包括文件存储,SharedPreferences存储,还有就是Acndroid中的特色:SQLite数据库存储了。让我比较惊讶的是Android中竟然内嵌了一个轻量型的数据库SQLite数据库,使得本地的数据持久化有了一个质的飞跃。
通过前两天上课听老师讲解,和课下自己看书总结,想在博客上把自己对于SQLite数据库的理解做一下总结,也是方便之后的复习。Android为了让我们能够更加方便的管理数据库,专门提供了SQLiteOpenHelper帮助类,这个类是一个抽象类,在这个类中,有两个抽象方法,一个是onCreate(),一个是onUpdate(),我们必须在自己的帮助类中继承SQLiteOpenHelper,并实现这两个抽象方法,并分别在这两个抽象方法中完成表的创建和数据库的更新和维护。SQLiteOpenHelper中还有两个非常重要的实例方法,getReadableDatabase()和getWriteableDatabase()。这两个方法都可以打开或创建一个现有的数据库(若数据库已经存在久直接打开,否则创建一个新的数据库),并返回一个可对数据库进行操作的对象。不同的是,当数据库不可以写入的时候(如磁盘空间已满),getReadableDatabase()方法返回的对象以只读的方式打开数据库,而getWriteableDatabase()方法出现异常(正如常常情况下使用二者获得的对象都具有读写功能)。SQLiteOpenHelper有两个构造方法可以重写,这里我们选择参数少的那一个。这个构造方法里面接收4个参数,第一个参数Context,这个没什么好说的,代表上下文,必须要有它才能对数据库进行操作;第二个参数是数据库名,他代表我们将要创建的数据库的名字;第三个参数允许我们创建数据库的时候返回一个自定义的Curs o r,一般都是传入nu ll;第四个参数代表当前数据库的版本号,可以用于数据库升级操作
构建出SQLiteOpenHelper实例后,再调用它的getReadableDatabase()或着getWriteableDatabase()方法就可以创建出数据库了,数据库文件会存放在/data/data/
SQLite数据库不像其他数据库拥有众多繁杂的数据类型,它的常用的数据类型很简单:integer代型,real代表浮点型,text代表文本型,blob代表二进制类型。
由于创建好的数据库虽然能在File Explorer中看到, 但却不能看到其内部包含的表,还有表中的数据,所以我们在这里使用adb shell来查看,使用adb shell需要配置adb的环境变量在这里不再叙述,网上有简单的教程。配置好环境变量后,Win+R中输入cmd进入命令提示符模式,输入adb shell进入adb环境,然后输入命令:cd /data/data/
首先创建我们自己的SQLOpenHelper类继承自SQLiteOpenHelper,并重写其中的方法和构造函数:
1 package com.example.databasetest; 2 3 import android.content.Context; 4 import android.database.sqlite.SQLiteDatabase; 5 import android.database.sqlite.SQLiteDatabase.CursorFactory; 6 import android.database.sqlite.SQLiteOpenHelper; 7 8 public class SqlOpenHelper extends SQLiteOpenHelper { 9 10 public static final String CREATE_BOOK = "create table book(" 11 + "id integer primary key autoincrement, " 12 + "name text," 13 + "price real)"; 14 public SqlOpenHelper(Context context, String name, CursorFactory factory, 15 int version) { 16 super(context, name, factory, version); 17 // TODO Auto-generated constructor stub 18 } 19 20 @Override 21 public void onCreate(SQLiteDatabase db) { 22 // TODO Auto-generated method stub 23 db.execSQL(CREATE_BOOK); 24 } 25 26 @Override 27 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 28 // TODO Auto-generated method stub 29 } 30 } 31 32 }
可以看到我们在重写的onreate方法中调用SQLiteDatbas的execSQL()方法建了一个表book
然后在我们的主界面中添加了四个按钮,用于创建数据库病完成CRUD操作:
我们在MainActivity中注册并实例化了四个按钮,并注册按钮的监听事件:
1 1 package com.example.databasetest; 2 2 3 3 import android.app.Activity; 4 4 import android.content.ContentValues; 5 5 import android.database.Cursor; 6 6 import android.database.sqlite.SQLiteDatabase; 7 7 import android.os.Bundle; 8 8 import android.util.Log; 9 9 import android.view.View; 10 10 import android.view.View.OnClickListener; 11 11 import android.widget.Button; 12 12 import android.widget.Toast; 13 13 14 14 public class MainActivity extends Activity implements OnClickListener { 15 15 16 16 private Button btn1,btn2,btn3,btn4; 17 17 private SqlOpenHelper helper; 18 18 private SQLiteDatabase db; 19 19 @Override 20 20 protected void onCreate(Bundle savedInstanceState) { 21 21 super.onCreate(savedInstanceState); 22 22 setContentView(R.layout.activity_main); 23 23 helper=new SqlOpenHelper(this, "book_store", null, 1); 24 24 btn1=(Button) findViewById(R.id.btn1); 25 25 btn2=(Button) findViewById(R.id.btn2); 26 26 btn3=(Button) findViewById(R.id.btn3); 27 27 btn4=(Button) findViewById(R.id.btn4); 28 28 btn1.setOnClickListener(this); 29 29 btn2.setOnClickListener(this); 30 30 btn3.setOnClickListener(this); 31 31 btn4.setOnClickListener(this); 32 32 } 33 33 34 34 35 35 @Override 36 36 public void onClick(View v) { 37 37 // TODO Auto-generated method stub 38 38 switch (v.getId()) { 39 39 case R.id.btn1: 40 40 db = helper.getWritableDatabase(); 41 41 db.beginTransaction(); //开始事务 42 42 try { 43 43 ContentValues values=new ContentValues(); 44 44 values.put("name", "Android"); 45 45 values.put("price", 16.5); 46 46 values.put("category_id", "1"); 47 47 db.insert("book", null, values); 48 48 db.setTransactionSuccessful(); //事务已经成功执行 49 49 Toast.makeText(this, "Create Success", Toast.LENGTH_SHORT).show(); 50 50 } catch (Exception e) { 51 51 // TODO Auto-generated catch block 52 52 e.printStackTrace(); 53 53 }finally{ 54 54 db.endTransaction(); //结束事务 55 55 db.close(); 56 56 } 57 57 break; 58 58 case R.id.btn2: 59 59 db=helper.getWritableDatabase(); 60 60 ContentValues values=new ContentValues(); 61 61 values.put("name", "zhangsan"); 62 62 values.put("price", 20); 63 63 db.update("book", values, "id=?", new String[]{5+""}); 64 64 break; 65 65 case R.id.btn3: 66 66 db=helper.getWritableDatabase(); 67 67 db.delete("book", "id=?",new String[]{1+""} ); 68 68 break; 69 69 case R.id.btn4: 70 70 db=helper.getWritableDatabase(); 71 71 Cursor cursor=db.query("book", null, null, null, null, null, "id DESC"); 72 72 while(cursor.moveToNext()){ 73 73 String name=cursor.getString(cursor.getColumnIndex("name")); 74 74 String price=String.valueOf(cursor.getFloat(2)); 75 75 Log.d("MainActivity", name); 76 76 Log.d("MainActivity", price); 77 77 } 78 78 break; 79 79 default: 80 80 break; 81 81 } 82 82 } 83 83 84 84 }
其中btn1代表创建数据库并向数据库中添加数据,btn2的点击事件是向数据库中更新数据,btn3则是删除操作,btn4是最为复杂的查询操作。
在向表中插入数据的时候,用到了事务,事务中的操作是要么都做,要么都不做,可以保证数据的正确。在每次操作数据库前,先使用我们自定义的帮助类的getWriteableDatabase()来打开(创建)数据库,并返回一个SQLiteDatabase类型的可操作对象。
添加数据:
调用SQLiteDatabase的insert方法,我们使用方法中有三个参数的那个就可以,第一个参数代表要操作的数据库表名,第二个参数表示哪列的值为空,一般填null,第三个参数则表示要插入的数据,是为ContentValues类型,ContentValues类型的变量有一个put方法,可以将数据以键-值对的形式存储。
更新数据:
SQLiteDatabase.update方法,我们使用有四个参数的方法,第一个参数还是代表我们要操作的数据库,第二个参数是要更新的值,为ContentValues类型,还是通过他的put方法来将要更新的值以键-值对的形式存储,第三个参数是相当于where条件,它跟第四个参数以占位符的方式来组成where条件,控制更新哪些满足条件的行。如:
db.update("book", values, "id=?", new String[]{5+""}); id=? 第四个参数中的值则为'?'部分内容
若这两个参数填null,则更新所有行。该方法返回一个整型结果,为受影响行数。
删除数据:
SQLiteDatabase.delete方法,该方法有三个参数,第一个参数是代表我们要操作的数据库,第二个第三个参数与update中的基本一样,不在叙述。
查询数据:
也是数据库中最为复杂的一种操作,在此只简单地说下其用法,数据库的查询方法返回一个Cursor类型变量,我们通过Cursor的moveToNext方法来取出查询结果。查询有好多种写法可以使用,比如本Demo中的SQLiteDatabase.query方法,接收7个参数,不过我们不用担心,我们先不去管这些参数,只用第一个参数:要查询的表。和最后一个参数:按照id降序排列。然后再一个while循环中通过Cursor.getString()将值取出来。此方法的7个参数含义如下:
使用上面的方法来操作数据库得益于Android给我们提供的方便的API,这样即使我们不太懂SQL语言,也可以做出操作数据库的操作,但其实我们还可以使用SQL方式来操作数据库:
添加数据的方法:
db.execSQL("insert into book(name,price) values("haha",23)"); //sql语句方式
db.execSQL("insert into book(name,price) values(?,?)",new String[]{"haha",34}); //占位符的方式
更新数据:
db.execSQL("update book set name=? where id=?",new String[]{"pig",2+""});
删除数据:
db.execSQL("delete from book where id>?",new String[]{"3"});
查询数据:
db.rawQuery("select * from book",null); //第二个参数是查询条件