Android本地数据存储之SQLite关系型数据库 ——SQLiteDatabase
数据库的创建,获取,执行sql语句:
框架搭建:dao
思考:
1.数据库保存在哪里?
2.如何创建数据库?如何创建表?
3.如何更新数据库?如何更改表的列数据?
4.如何获取数据库?
5.如何修改数据库中的表的数据?
框架思想
思考:如何使得编程更加简单?
一个sql语言,容易写错;
1.使用占位符;
2.框架解析重建法:搭建框架,对增删改查功能进行单独封装,传入容器对象即可;
思考:
1.数据库保存在哪里?
data/data/包名/databases/xiaoo.db
2.如何创建数据库?如何创建表?
db.execSQL("CREATE TABLE person (personid integer primary key autoincrement, name varchar(20))");
3.如何更新数据库?如何更改表的列数据?
db.execSQL("ALTER TABLE person ADD phone VARCHAR(12) NULL ");
4.如何获取数据库?
5.如何修改数据库中的表的数据?
一、创建数据库打开助手:
二、创建dao
三、测试dao
- import android.content.Context;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteOpenHelper;
- public class MyDBOpenHelper extends SQLiteOpenHelper {
- /**
- *
- * @param context 应用程序上下文
- * @param name 数据库的名字
- * @param factory 查询数据库的游标工厂 一般情况下 用sdk默认的
- * @param version 数据库的版本 版本号必须不小1
- *
- */
- public MyDBOpenHelper(Context context) {
- super(context, "xiaoo.db", null, 6);
- }
- // 在mydbOpenHelper 在数据库第一次被创建的时候 会执行onCreate();
- @Override
- public void onCreate(SQLiteDatabase db) {
- System.out.println("我被调用了 oncreate");
- db.execSQL("CREATE TABLE person (personid integer primary key autoincrement, name varchar(20))");
- }
- // 通过version的增加来执行数据库版本更新,版本号改为6的同时,调用onUpgrade ,让程序员执行具体更新;
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- System.out.println("on update ");
- db.execSQL("ALTER TABLE person ADD phone VARCHAR(12) NULL ");
- }
- }
二、创建dao
- import java.util.ArrayList;
- import java.util.List;
- import android.content.Context;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import android.util.Log;
- import cn.itcast.db.MyDBOpenHelper;
- import cn.itcast.db.domain.Person;
- public class PersonDao {
- private static final String TAG = "PersonDao";
- private MyDBOpenHelper dbOpenHelper;
- // 在personDao被new出来的时候 就完成初始化
- public PersonDao(Context context) {
- dbOpenHelper = new MyDBOpenHelper(context);
- // dbOpenHelper.getReadableDatabase()
- // dbOpenHelper.getWritableDatabase()
- }
- // 增删改查
- /**
- * 往数据库添加一条数据
- */
- public void add(String name, String phone) {
- boolean result = find(name);
- if (result)
- return;
- SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
- if (db.isOpen()) {
- db.execSQL("insert into person (name,phone) values (?,?)",
- new Object[] { name, phone });
- // 关闭数据库 释放数据库的链接
- db.close();
- }
- }
- /**
- * 查找数据库的操作
- */
- public boolean find(String name) {
- boolean result = false;
- SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
- if (db.isOpen()) {
- Cursor cursor = db.rawQuery("select * from person where name=?",
- new String[] { name });
- if (cursor.moveToFirst()) {
- int index = cursor.getColumnIndex("phone"); // 得到phone在表中是第几列
- String phone = cursor.getString(index);
- Log.i(TAG, "phone =" + phone);
- result = true;
- }
- // 记得关闭掉 cursor
- cursor.close();
- result = false;
- // 释放数据库的链接
- db.close();
- }
- return result;
- }
- /**
- * 删除一条记录
- *
- * @param name
- */
- public void delete(String name) {
- SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
- if (db.isOpen()) {
- db.execSQL("delete from person where name =?",
- new Object[] { name });
- db.close();
- }
- }
- /**
- * 更新一条记录
- *
- */
- public void update(String name, String newname, String newphone) {
- SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
- if (db.isOpen()) {
- db.execSQL("update person set name=? , phone=? where name=?",
- new Object[] { newname, newphone, name });
- db.close();
- }
- }
- /**
- * 查找全部
- */
- public List<Person> getAllPersons() {
- List<Person> persons=null;
- SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
- if (db.isOpen()) {
- persons = new ArrayList<Person>();
- Cursor cursor = db.rawQuery("select * from person ", null);
- while (cursor.moveToNext()) {
- Person person = new Person();
- int nameindex = cursor.getColumnIndex("name");
- int phoneindex = cursor.getColumnIndex("phone");
- String name = cursor.getString(nameindex);
- String phone = cursor.getString(phoneindex);
- person.setName(name);
- person.setNumber(phone);
- persons.add(person);
- }
- cursor.close();
- db.close();
- }
- return persons;
- }
- }
三、单元测试:测试dao
1.配置
- instrumentation 和 uses-library
- <instrumentation
- android:name="android.test.InstrumentationTestRunner" //使用测试框架中的哪个测试运行器
- android:targetPackage="cn.xiaoo.db" /> //测试哪个工程?
- <application
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name" >
- <uses-library android:name="android.test.runner" /> //该程序需要添加哪个jar包(用于测试)?
2.编程测试
- package cn.itcast.db.dao.test;
- import java.util.List;
- import cn.itcast.db.dao.PersonDao;
- import cn.itcast.db.domain.Person;
- import android.test.AndroidTestCase;
- public class TestPersonDao extends AndroidTestCase {
- PersonDao dao;
- // 测试在执行测试代码时候的流程
- //1 .new TestPersonDao 框架new出来
- //2. 调用 setUp()
- //3. testAdd() 这个时候 上下文 才被创建出来
- /* @Override
- protected void setUp() throws Exception {
- dao = new PersonDao(getContext());
- super.setUp();
- }*/
- public void testAdd() throws Exception{
- PersonDao dao = new PersonDao(getContext());
- for(int i=0;i<100;i++){
- dao.add("lisi"+i, "123456789"+i);
- }
- }
- public void testdelete() throws Exception{
- PersonDao dao = new PersonDao(getContext());
- dao.delete("lisi99");
- }
- public void testupdate() throws Exception{
- PersonDao dao = new PersonDao(getContext());
- dao.update("lisi98", "wangwu", "120");
- }
- public void testFindAll() throws Exception{
- PersonDao dao = new PersonDao(getContext());
- List<Person> persons = dao.getAllPersons();
- assertEquals("testFindAll获取集合的大小",98, persons.size());
- }
- /**
- * 测试的流程:
- */
- /*
- [2012-10-05 13:47:51 - db] ------------------------------
- [2012-10-05 13:47:51 - db] Android Launch! //系统启动
- [2012-10-05 13:47:51 - db] adb is running normally. //调试桥正常运行
- [2012-10-05 13:47:51 - db] Performing android.test.InstrumentationTestRunner JUnit launch //运行测试运行器,启动JUnit
- [2012-10-05 13:47:51 - db] Automatic Target Mode: using existing emulator 'emulator-5554' running compatible AVD '2.3.3_QVGA'
- [2012-10-05 13:47:53 - db] Application already deployed. No need to reinstall.//不需要重新安装
- [2012-10-05 13:47:53 - db] Launching instrumentation android.test.InstrumentationTestRunner on device emulator-5554//在设备上运行测试运行器
- [2012-10-05 13:47:53 - db] Collecting test information //收集运行信息
- [2012-10-05 13:47:56 - db] Sending test information to Eclipse //发送测试信息到Eclipse
- [2012-10-05 13:47:56 - db] Running tests... //执行代码
- [2012-10-05 13:47:58 - db] Test run finished //执行完毕
- */
- }
框架思想
思考:如何使得编程更加简单?
一条sql语句,容易写错;
- 操作表
- insert into person (name,phone) values (?,?)---------public long insert(String table, String nullColumnHack, ContentValues values)
- delete from person where name =?---------------------public int delete(String table, String whereClause, String[] whereArgs)
- update person set name=? , phone=? where name=?------public int update(String table, ContentValues values, String whereClause, String[] whereArgs)
- select * from person where name=?--------------------public Cursor query(boolean distinct, String table, String[] columns,
- String selection, String[] selectionArgs, String groupBy,
- String having, String orderBy, String limit)
- insert:在哪张表插入哪些数据?string string contentvalues
- delete:在哪张表删除哪些数据?String String String[]
- update:在哪张表的那条数据上更改什么数据? String ContentValues String String[]
- query:是否保证唯一?查哪张表?查哪些列?
- 什么查询条件?占位符值?分组?
- 包含?排序?区间?
- 操作数据库:
- CREATE TABLE person (personid integer primary key autoincrement, name varchar(20))
- ALTER TABLE person ADD phone VARCHAR(12) NULL
怎办办?
1.使用占位符;
2.框架解析重建法:搭建框架,对增删改查功能进行单独封装,传入容器对象即可;
- 1.原生: db.execSQL("insert into person (name,age) values ("xiaoli",20)");
- 2.站位符:db.execSQL("insert into person (name,age) values (?,?)",new Object[]{"xiaoli",20});
- 3.框架 :
- ContentValues values = new ContentValues();
- values.put("name", name);
- values.put("age", age);
- db.insert("person", null, values);
- public void add(String name, int age) {
- SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
- if (db.isOpen()) {
- ContentValues values = new ContentValues();
- values.put("name", name);
- values.put("age", age);
- // 如果 contentvalues为空
- db.insert("person", null, values); // 组拼sql语句完成的添加的操作
- // insert into person name values (NULL) ;
- db.close();
- }
- }
最复杂的方法是查询:query
我们一起来看看底层是怎么封装的:
- public static String buildQueryString(
- boolean distinct, String tables, String[] columns, String where,
- String groupBy, String having, String orderBy, String limit) {
- if (TextUtils.isEmpty(groupBy) && !TextUtils.isEmpty(having)) {
- throw new IllegalArgumentException(
- "HAVING clauses are only permitted when using a groupBy clause");
- }
- if (!TextUtils.isEmpty(limit) && !sLimitPattern.matcher(limit).matches()) {
- throw new IllegalArgumentException("invalid LIMIT clauses:" + limit);
- }
- StringBuilder query = new StringBuilder(120);
- query.append("SELECT ");
- if (distinct) {
- query.append("DISTINCT ");
- }
- if (columns != null && columns.length != 0) {
- appendColumns(query, columns);
- } else {
- query.append("* ");
- }
- query.append("FROM ");
- query.append(tables);
- appendClause(query, " WHERE ", where);
- appendClause(query, " GROUP BY ", groupBy);
- appendClause(query, " HAVING ", having);
- appendClause(query, " ORDER BY ", orderBy);
- appendClause(query, " LIMIT ", limit);
- return query.toString();
- }
另一种增删改查:dao
- import java.util.ArrayList;
- import java.util.List;
- import cn.itcast.db.MyDBOpenHelper;
- import cn.itcast.db.domain.Person;
- import android.content.ContentValues;
- import android.content.Context;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- public class PersonDBDao {
- private Context context;
- MyDBOpenHelper dbOpenHelper;
- public PersonDBDao(Context context) {
- this.context = context;
- dbOpenHelper = new MyDBOpenHelper(context);
- }
- /**
- * 添加一条记录
- */
- public void add(String name, int age) {
- SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
- if (db.isOpen()) {
- // db.execSQL("insert into person (name,age) values (?,?)",new
- // Object[]{name,age});
- // db.execSQL("insert into person ",null) // 不合法的sql语句
- ContentValues values = new ContentValues();
- values.put("name", name);
- values.put("age", age);
- // 如果 contentvalues为空
- db.insert("person", null, values); // 组拼sql语句完成的添加的操作
- // insert into person name values (NULL) ;
- db.close();
- }
- }
- /**
- * 删除一条记录
- */
- public void delete(String name) {
- SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
- if (db.isOpen()) {
- db.delete("person", "name=?", new String[] { name });
- db.close();
- }
- }
- /**
- * 数据库的更改操作
- */
- public void update(String name, String newname, int newage) {
- SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
- if (db.isOpen()) {
- ContentValues values = new ContentValues();
- values.put("name", newname);
- values.put("age", newage);
- db.update("person", values, "name=?", new String[] { name });
- db.close();
- }
- }
- /**
- * 数据库的查询操作
- */
- public boolean find(String name) {
- boolean result = false;
- SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
- if (db.isOpen()) {
- // select * from person
- Cursor cursor = db.query("person", null, "name=?",
- new String[] { name }, null, null, null);
- if (cursor.moveToFirst()) {
- result = true;
- }
- cursor.close();
- db.close();
- }
- return result;
- }
- /**
- * 查询所有信息
- */
- public List<Person> findAll() {
- List<Person> persons = null;
- SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
- if (db.isOpen()) {
- Cursor cursor = db.query("person", null, null, null, null, null,
- null);
- persons = new ArrayList<Person>();
- while (cursor.moveToNext()) {
- Person person = new Person();
- String name = cursor.getString(cursor.getColumnIndex("name"));
- person.setName(name);
- int age = cursor.getInt(cursor.getColumnIndex("age"));
- person.setAge(age);
- persons.add(person);
- }
- cursor.close();
- db.close();
- }
- return persons;
- }
- /**
- * 查询所有信息
- */
- public Cursor findAllbyCursor() {
- SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
- if (db.isOpen()) {
- /*Cursor cursor = db.query("person", null, null, null, null, null,
- null);*/
- Cursor cursor = db.rawQuery("select personid as _id,age,name from person", null);
- return cursor;
- // 注意了 一定不要把数据库 关闭了
- }
- return null;
- }
- /**
- * 银行转账的方法
- * 1.开始事务:db.beginTransaction();
- * 2.设置事务成功:db.setTransactionSuccessful();
- * 3.结束事务:db.endTransaction();
- * 4.关闭连接:db.close();
- */
- public void transaction() {
- SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
- if (db.isOpen()) {
- try {
- // 开启数据库的事务
- db.beginTransaction();
- // 给张三设置1000块钱的账户
- db.execSQL("update person set account=? where name=?",
- new Object[] { 1000, "zhangsan98" });
- // 把张三的账户扣除200块钱
- db.execSQL("update person set account=account-? where name=?",
- new Object[] { 200, "zhangsan98" });
- // 出现了异常
- // 把张三的钱给李四
- //初始化李四账户 为 0
- db.execSQL("update person set account=? where name=?",
- new Object[] { 0, "lisi" });
- db.execSQL("update person set account=account+? where name=?",
- new Object[] { 200, "lisi" });
- db.setTransactionSuccessful();
- }
- // 显示的设置事务是否成功
- catch (Exception e) {
- // TODO: handle exception
- } finally {
- db.endTransaction();
- db.close();
- }
- }
- }
- }