数据库相关(5) SQLite

在安卓系统,涉及到数据存储的,主要有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 );
			}	
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值