您的位置:首页 > 数据库

数据库相关(5) SQLite

2015-07-31 16:39 369 查看
在安卓系统,涉及到数据存储的,主要有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来往下读取。因为查询的目的是为了读取数据库里的数据,某些字段什么的,形象来说,是一节一节的读取。

Cursor是结果集游标,用于对结果集进行随机访问,如果大家熟悉jdbc, 其实Cursor与JDBC中的ResultSet作用很相似。使用moveToNext()方法可以将游标从当前行移动到下一行,如果已经移过了结果集的最后一行,返回结果为false,否则为true。另外Cursor 还有常用的moveToPrevious()方法(用于将游标从当前行移动到上一行,如果已经移过了结果集的第一行,返回值为false,否则为true )、moveToFirst()方法(用于将游标移动到结果集的第一行,如果结果集为空,返回值为false,否则为true
)和moveToLast()方法(用于将游标移动到结果集的最后一行,如果结果集为空,返回值为false,否则为true ) 。

下面的Demo是在布局文件里写了button,这里就不贴上来了

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 & 第一类方法

在Android系统,提供了一个SQLiteOpenHelper抽象类,该类用于对数据库版本进行管理.
需要继承这个抽象来,实现一个有参构造函数和两个方法



他的构造方法用来接收参数再来创建一个数据库

这个抽象类一般是用来版本控制,表结构有变动,或者说升级什么的,这就是upgrade方法的用处,在调用这个抽象类创建数据库的时候,还可以在他的oncreate方法里去创建表(第一次才有用)

//一般用来查询,创建数据库的时候,可以插入一些数据,或者建表什么的
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
另外再helper里可以创建表,而且是数据库被创建时才会调用一次,无需在activity里去建表了,以后再调用这个openhelper只是进行查询操作

在版本升级时,要增加一些功能加别的表什么的,就要调用upgrade,添加新表什么的,同时版本号必须变动

在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 );
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: