在安卓系统,涉及到数据存储的,主要有4种情况
文件读写 openFileOutput()方法 FileOutputStream outStream = this.openFileOutput("cskaoyan.txt", Context.MODE_PRIVATE);
sharedPreference SharedPreferences sharedPreferences = getSharedPreferences("infomation", 0);
网络数据
SQLite
1. 在SQLite中,增删改查的语句有两种写法
一种是对应每类操作的专门方法,insert()等等,略过不提了
第二种是execSQL和rawQuery两种方法,前者执行数据库变动的方法,建表,增删改;后者专门用来进行查询操作,与第一种方法的区别是,这两个方法里面直接填入SQL的通用操作语句即可,很方便。
exec方法, 实际操作中,我们通常是在外接收数据来进行操作,这里涉及到一些特殊符号的转义问题,直接写比较麻烦,所以用一个object对象来接收,有一个重载后的execSQL(String sql, Object[] bindArgs)方法,前面的sql里面可以用占位符 ? 来替代具体参数,把具体参数传给object即可
raw方法,第一个参数为select语句;第二个参数为select语句中占位符参数的值,如果select语句没有使用占位符,该参数可以设置为null。需要注意在执行raw后返回一个cursor,要通过这个cursor来往下读取。因为查询的目的是为了读取数据库里的数据,某些字段什么的,形象来说,是一节一节的读取。
public class MainActivity extends Activity {
public static String TAG ="sqlitedemo";
SQLiteDatabase db=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建数据库
db = SQLiteDatabase.openOrCreateDatabase(getFilesDir()+"userinfo.db", null);
}
public void insert(View v){
insert(db);
}
public void delete(View v){
delete(db);
}
public void update(View v){
Update(db);
}
public void query(View v){
query(db);
}
private void Update(SQLiteDatabase db) {
/*String update = "update user set password ='88888888' where id =2;";
db.execSQL(update);*/
String update = "update user set password =? where id =?;";
Object[] args = {"99999999",5};
db.execSQL(update,args);
}
private void delete(SQLiteDatabase db) {
/* String delete = "delete from user where id =1;";
db.execSQL(delete);*/
String delete = "delete from user where id =?;";
Object[] args = {5};
db.execSQL(delete,args);
}
private void query(SQLiteDatabase db) {
//查询,并弄到名为resultset的Cursor类的集合里
String sql = "select * from user where id = ? and name =?;";
String[] arg = {"1","user1"};
Cursor resultset = db.rawQuery(sql, arg);
//先在resultset里找到行数
int row = resultset.getCount();
//sqlite列标从0开始,mysql从1开始
Log.i(TAG, row+"");
//Cursor的游标指向了数据的前一行,所以需要next
while(resultset.moveToNext()){
int id = resultset.getInt(0);
String username= resultset.getString(1);
String password= resultset.getString(2);
Log.i(TAG, id+","+username+","+password);
}
}
private void insert(SQLiteDatabase db) {
/*String insert = "insert into user values(5,'user5','12345');";
db.execSQL(insert);*/
String insert = "insert into user values(?,?,?);";
Object[] args = {4,"user4","55555555"};
db.execSQL(insert, args);
}
private void createTable(SQLiteDatabase db) {
String createtable = "create table user(id int,name varchar(20),password char(8));";
db.execSQL(createtable);
}
}
2. SQLiteOpenHelper & 第一类方法
//一般用来查询,创建数据库的时候,可以插入一些数据,或者建表什么的
public class MydbOpenHelper extends SQLiteOpenHelper {
//在调用的时候,把要创建的数据库名保存起来
//然后在调用Helper获取数据库的时候,用这个名字创建数据库
public MydbOpenHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
}
//oncreate函数当数据库第一次被创建的时候才会被调用
//上面提到的建表、插入数据什么的就在oncreate里实现
@Override
public void onCreate(SQLiteDatabase db) {
String createtable = "create table user(id int,name varchar(20),password char(8));";
db.execSQL(createtable);
System.out.println("MydbOpenHelper.onCreate()");
}
//数据库版本升级的时候调用,不会把原有User数据删掉
//之前版本没有的、或者需要变动的,使用Upgrade
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//在这里对传送过来的db进行改动,比如加一个gender属性,然后下面执行
//db.execSQL(sql);
//看看有没有调用到
Log.i("MydbOpenHelper", "oldervserion"+oldVersion+"newversion"+newVersion);
System.out.println("MydbOpenHelper.onUpgrade()");
}
}
public class MainActivity extends Activity {
SQLiteDatabase db=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//此时数据还没有被创建出来
MydbOpenHelper dbhelper = new MydbOpenHelper(this,"userinfo.db",null,1);
//调用下条语句之后,数据库才会被创建出来
//SQLiteDatabase db = dbhelper.getWritableDatabase();
//磁盘满了的话创建的数据库是只读的,不能写,比write强一点
SQLiteDatabase db = dbhelper.getReadableDatabase();
/*//可以使用这个原始方法,但是在openhelper里有google封装好的
String createtable = "create table user(id int,name varchar(20),password char(8));";
db.execSQL(createtable);*/
为了防止溢出,用readable
在activity里有了新版本后,必须说要先在openhelper里添加新的功能,然后才能在activity里去查询什么的
比如数据库里添加了一个gender的字段,数据库版本就变动了,数据库变动就会调用这个upgrade方法,在这里应该实现添加字段的功能,然后才可以在activity里去查询这个字段。
//数据库版本升级的时候调用,不会把原有User数据删掉
//之前版本没有的、或者需要变动的,使用Upgrade
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//在这里对传送过来的db进行改动,比如加一个gender属性,然后下面执行
//db.execSQL(sql);
//看看有没有调用到
Log.i("MydbOpenHelper", "oldervserion"+oldVersion+"newversion"+newVersion);
System.out.println("MydbOpenHelper.onUpgrade()");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*//此时数据还没有被创建出来
MydbOpenHelper dbhelper = new MydbOpenHelper(this,"userinfo.db",null,1);
//调用下条语句之后,数据库才会被创建出来
//SQLiteDatabase db = dbhelper.getWritableDatabase();
//磁盘满了的话创建的数据库是只读的,不能写,比write强一点
SQLiteDatabase db = dbhelper.getReadableDatabase();
//可以使用这个原始方法,但是在openhelper里有google封装好的
String createtable = "create table user(id int,name varchar(20),password char(8));";
db.execSQL(createtable);*/
//新的db,版本6
MydbOpenHelper dbhelper = new MydbOpenHelper(this,"userinfo.db",null,6);
db = dbhelper.getReadableDatabase();
/*String sql = "select gender from user;";
db.execSQL(sql);*/
}
再来看第一类方法
public void insert(View v){
//需要new一个,而不是Null
ContentValues c = new ContentValues();
c.put("id", 1);
c.put("name", "user1");
c.put("password", "123454");
//table往哪个表插,values是个map,键值对,定义键名和值(默认8)
//columnHack
db.insert("user", null, c);
}
public void delete(View v){
db.delete("user", " id =? and name =? ", new String[]{"1", "user1"});
}
public void update(View v){
//Update(db);
ContentValues c = new ContentValues();
c.put("name", "user22222");
c.put("password", "88888888");
db.update("user", c, "id=?", new String[]{"2"});
}
public void query(View v){
String[] colums ={"id","name"};
String[] args = {"1","12345"};
Cursor c = db.query("user",colums,"id=? and password=?",args , null,null,null);
while(c.moveToNext()){
int id = c.getInt(c.getColumnIndex("id"));
String username= c.getString(c.getColumnIndex("name"));
Log.i("sqliteopenhelper", id+","+id+","+username);
}
}
3. 事务处理
ContentValues:数据库插入、更新数据的时候用到,应该是一个map,一个key,一个value。一个数据表的Column,一个存入的值。返回的是数组。它和HashTable类似都是一种存储的机制,contenvalues只能存储基本类型的数据,而HashTable却可以存储对象
在向数据库中插入数据的时候,首先应该有一个ContentValues的对象
public class MainActivity extends Activity {
SQLiteDatabase db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MydbOpenHelper helper = new MydbOpenHelper(this,"count.db",null,1);
db = helper.getReadableDatabase();
try{
insert();
update();
}finally{
db.close();
}
}
private void update() {
db.beginTransaction();
try{
ContentValues contentValues = new ContentValues();
contentValues.put("money", 7000);
db.update("user", contentValues, "id=1", null);
int b = 1/0;
contentValues.clear();
contentValues.put("money", 11000);
db.update("user", contentValues, "id=2", null);
db.setTransactionSuccessful();
}finally{
//commit 提交
//不成功则回滚
db.endTransaction();
}
}
private void insert() {
ContentValues contentValues = new ContentValues();
contentValues.put("id",1);
contentValues.put("name","user1");
contentValues.put("money",8000);
db.insert("user", null, contentValues);
contentValues.put("id",2);
contentValues.put("name","user2");
contentValues.put("money",1000);
db.insert("user", null, contentValues);
}
}
和之前在MySQL里差不多
有一点要注意,SQLite里下标从0开始计算的,mysql什么的是从1计数
4.SQLite有一个命令行的查询工具,不过现在又现成的图形界面的数据库管理软件,例如SQLite Expert
5.测试
为了方便测试数据库,无需去启动UI画面来看结果,可以写一个AndroidTestCase类,这个类也要在虚拟机上安装,但是会自动销毁,不显示画面
这个还要去manifest里声明
<pre name="code" class="java">
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />
<!-- test指令集 -->
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.example.sqliteopenhelper"
>
</instrumentation>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<!-- 测试类库 -->
<uses-library android:name="android.test.runner"/>
<activity
在某个项目里加上测试类就好
public class MyAndroidTestCase extends AndroidTestCase {
SQLiteDatabase db;
@Override
protected void setUp() throws Exception {
// TODO Auto-generated method stub
super.setUp();
MydbOpenHelper dbhelper = new MydbOpenHelper(getContext(), "userinfo.db", null, 6);
db = dbhelper.getReadableDatabase();
Log.i("test", "setUp()");
}
//自动销毁测试
@Override
protected void tearDown() throws Exception {
// TODO Auto-generated method stub
super.tearDown();
db.close();
Log.i("test", "tearDown()");
}
//选中这个方法,右键测试跑起就好
public void testcase1(){
testinsert();
testquery();
}
public void testinsert(){
ContentValues c = new ContentValues();
c.put("id", 9);
c.put("name", "user2");
c.put("password", "123454");
db.insert("user", null, c);
}
public void testquery(){
Cursor c= db.rawQuery("select * from user", null);
while (c.moveToNext()) {
//表示由mydbopenhelper里的onCreate创建,可以去看下结构
int id= c.getInt(0);
String name= c.getString(1);
String password= c.getString(2);
Log.i("test", id+","+name+","+password );
}
}
}