Android 存储数据之3 使用SQLite数据库存储

   SQLite是Android内置的数据库,轻量级的,它的运算速度非常快.Android为了让我们能够更加方便的管理数据库,专门提供了一个SQLiteOpenHelper帮助类,借助这个类就可以非常简单地对数据库进行创建和升级.SQLiteOpenHelper是一个抽象类.

    创建数据库,新建一个类去继承SQLiteopenHelper,实现onCreate()和onUpgrade()方法,构造方法选择参数少点的那个.


用命令行查看数据库时: adb shell 为了进入database cd data cd data ls 结果提示了adb
          opendir failed ,permission denied 和linux一样,这时候su回车
          然后在手机上同意root就行了(记得之前要开放手机的root权限)
 
          查表中数据:sqlite3 BookStore.db -> select * from Book; 此例中数据为: 1|Dan
          Brown|16.96|454|The Da Vinci Co 2|Dan Brown|19.95|510|The Lost Symbol
          如果在sqlite3命令中输入错误:sqlite> select * from Category ...> s 则需要在下一句的末尾输入
         ; 号,enter才能退出来


下面的代码对数据库进行了增删改查

public class MainActivity extends Activity {

	private Button create_database = null;
	private Button add_data = null;
	private Button update_data = null;
	private Button delete_data = null;
	private Button query_data = null;
	private Button replace_data = null;
	private MyDatabaseHelper dbHelper;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		/**
		 * context 上下文 name 数据库名称 factory 返回自定义的Cursor,一般传入null version 数据库版本
		 */
		// 创建数据库
		// mydata = new MyDatabaseHelper(MainActivity.this, "BookStore.db",
		// null,1);

		// 第二次执行这条语句,数据库版本是2,会执行到onUpgrade()
		dbHelper = new MyDatabaseHelper(MainActivity.this, "BookStore.db", null,
				2);

		create_database = (Button) findViewById(R.id.create_database);
		add_data = (Button) findViewById(R.id.add_data);
		update_data = (Button) findViewById(R.id.update_data);
		delete_data = (Button) findViewById(R.id.delete_data);
		query_data = (Button) findViewById(R.id.query_data);
		replace_data = (Button) findViewById(R.id.replace_data);

		// 创建表
		create_database.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				dbHelper.getWritableDatabase(); // 获取可读写的数据库
			}
		});

		//添加数据
		add_data.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				// 获得数据库实例,用来操作的
				SQLiteDatabase db = dbHelper.getWritableDatabase();
				// 这是ContentValues对象insert()方法的第三个参数,用来组装数据的
				ContentValues values = new ContentValues();

				// id那一列是自增长的,就不用设置
				// 开始组装第一条数据
				values.put("name", "The Da Vinci Code"); // 达芬奇密码
				values.put("author", "Dan Brown");
				values.put("pages", 454);
				values.put("price", 16.96);
				db.insert("Book", null, values); // 插入第一条数据

				values.clear(); // 清空values中的数据

				values.put("name", "The Lost Symbol");
				values.put("author", "Dan Brown");
				values.put("pages", 510);
				values.put("price", 19.95);
				db.insert("Book", null, values); // 插入第二条数据
			}
		});

		//更新数据
		update_data.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				SQLiteDatabase db = dbHelper.getWritableDatabase();
				ContentValues values = new ContentValues();
				values.put("price", 10.99);
				
				// 参数:表名,ContentValues对象封装的数据,更新哪一行(去更新name=?,而?占一个占位符),可以通过
				// 第四个参数提供的一个字符串数组为第三个参数中的每个占位符指定相应的内容.
				// 第三个参数对应sql语句的where部分
				int count = db.update("Book", values, "name = ?",
						new String[] { "The Da Vinci Code" });
				// 上述代码的意图是,将名字为"The DaVinci Code"的这本书价格改成10.99
			}
		});
		
		//删除数据
		delete_data.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				SQLiteDatabase db = dbHelper.getWritableDatabase();
				//表名,where部分,?
				//删除大于500页的书
				db.delete("Book", "pages > ?", new String[]{"500"});
			}
		});
		
		//查询数据
		query_data.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				//调用query()方法后悔返回一个Cursor对象,查询到的所有数据都将从这个对象中取出
				SQLiteDatabase db = dbHelper.getWritableDatabase();
				
				//参数:表名,列名,where部分,为占位符指定具体的值,group by的列,对group by后的结果进一步约束,查询结果排序方式
				//查询Book表中的所有数据,并存到Cursor对象中
				Cursor cursor = db.query("book", null, null, null, null, null, null, null);
				
				//moveToFirst()方法将数据的指针移动到第一行的位置,然后循环查询每一行的数据
				//通过Cursor的getColumnIndex()方法获取到某一列在表中对应位置索引
				//然后再将这个索引传入到相应的取值方法中,就可以得到从数据库中读取到的数据了
				//最后需要用close()方法关闭Cursor
				if(cursor.moveToFirst()){
					do{
						String name = cursor.getString(cursor.getColumnIndex("name"));
						String author = cursor.getString(cursor.getColumnIndex("author"));
					    int pages = cursor.getInt(cursor.getColumnIndex("pages"));
					    double price = cursor.getDouble(cursor.getColumnIndex("price"));
					    Log.d("xfhy","name :"+name);
					    Log.d("xfhy","author :"+author);
					    Log.d("xfhy","pages :"+pages);
					    Log.d("xfhy","price :"+price);
					    
					}while(cursor.moveToNext());
				}
				cursor.close();
			}
		});
		
		//使用事务,替换数据  要么删除旧数据和添加新数据的操作一起完成,要么就还要保留原来的旧数据
		//事务的特性就是保证让某一系列操作要么全部完成,要么一个都不会完成
		//这里是事务的标准写法
		replace_data.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				SQLiteDatabase db = dbHelper.getWritableDatabase();
				db.beginTransaction();  //开启事务
				try {
					db.delete("Book", null, null);  //这里表示删除Book表里的全部数据
					
					/*if(true){  //这里是故意让事务失败的,为了测试
						throw new NullPointerException();  //手动抛出异常,让事务失败
					}*/
					
					ContentValues values = new ContentValues();
					values.put("name", "Game of Thrones");
					values.put("author", "George Martin");
					values.put("pages", 720);
					values.put("price", 20.85);
					db.insert("Book",null,values);  //添加数据
					
					db.setTransactionSuccessful();   //事务已成功执行
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					db.endTransaction();   //结束事务
				}
			}
		});
		
		
	}
}

继承SQLiteOpenHelper,并完成构造方法的实现,实现onCreate()和onUpgrade()方法
  
  
  建表语句,integer是整型,text是文本,real是浮点型,blob是二进制类型
  
  用adb命令去打开数据库目录的话,需要将platform-tools配置到Path环境变量中去.然后cmd->adb shell
  打开数据库所在目录/data/data/com.example.databasetest/databases 
  再ls 可以看到当前的数据库BookStore.db已经在里面了,输入sqlite3 BookStore.db
  可以用sqlite3工具打开数据库,然后输入.schema可以显示当前数据库的创建的语句
  
  
  这里是升级数据库的最佳写法:
    用户是第一次安装这个软件,则建立2张表
    用户是升级数据库,则判断一下是不是通过老版本来更新的,只需要创建1张表Category即可
    这里升级数据库时,没有break语句,这是为了保证每一次的数据库修改都能被全部执行到.
比如我现在是数据库版本1,我安装了最新的软件,就需要升级到数据库版本3,就需要做1->2,2->3的所有操作



public class MyDatabaseHelper extends SQLiteOpenHelper{

	//存放书的各种详细数据
	private static final String CREATE_BOOK = "create table Book(" +
			"id integer primary key autoincrement, " +
			"author text, " +
			"price real, " +
			"pages integer, " +
			"name text, " +
			"category_id integer)";     //第三版的数据库(假设数据库升级),加了这个属性
	//存放分类名,分类代码等
	private static final String CREATE_CATEGORY = "create table Category (" +  //数据库升级到第二本时,新增了这个表
			"id integer primary key autoincrement, " +
			"category_name text, " +
			"category_code integer)";
	
	
	/**
	 * @param context  上下文
	 * @param name     数据库名称
	 * @param factory  返回自定义的Cursor,一般传入null
	 * @param version  数据库版本
	 */
	public MyDatabaseHelper(Context context, String name,
			CursorFactory factory, int version) {
		super(context, name, factory, version);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		//执行建表语句                                           用户是第一次安装这个软件,则建立2张表
		db.execSQL(CREATE_BOOK);
		db.execSQL(CREATE_CATEGORY);
		Log.d("xfhy","建表成功!");
	}

	//只有在更新数据库时,才会执行到这个方法   用户是升级数据库,则判断一下是不是通过老版本来更新的,只需要创建1张表Category即可
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		
		//这里升级数据库时,没有break语句,这是为了保证每一次的数据库修改都能被全部执行到.
		//比如我现在是数据库版本1,我安装了最新的软件,就需要升级到数据库版本3,就需要做1->2,2->3的所有操作
		switch (oldVersion) {
		case 1:  //如果原来的数据版本是1,则现在要升级数据库,需要建表
			db.execSQL(CREATE_CATEGORY);  //创建Category表
		case 2:  //如果原来的数据库版本是2,则现在要增加Book表的属性,需要执行以下sql语句
			db.execSQL("alter table Book add column category_id integer");
		default:
		}
	}

}


posted @ 2016-07-31 21:54  潇风寒月  阅读(8)  评论(0)    收藏  举报