• [Android]SQLite的使用


    Android 数据存储提供了四种存储方式:

    • Shared Preferences

        使用键值对(Map(key, value))来存储数据 
      
    • Internal Storage

        内部存储,存储在设备内存的 私人数据 
      
    • External Storage

        外部存储,存储在外部设备的 公共数据 
      
    • SQLite Databases

        存储在关系型数据库;SQLite 是类似MySQL 的关系型数据库,因为其体较小,功能全,被运用在了大多嵌入式设备 
      

    Network Connection

    SQLite 简介

    非常小的关系型数据库

    SQLiteOpenHelper

    CRUD(增删改查)

    
    import android.app.Activity;
    import android.content.ContentValues;
    import android.content.Context;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    
    public class SimpleActivity extends Activity {
    
        private static final String INFO = "SimpleActivity";
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.simple_layout);
            Log.i(INFO, INFO);
    
            SQLiteDatabase db = openOrCreateDatabase("simple.db", Context.MODE_PRIVATE, null);
            db.execSQL("DROP TABLE IF EXISTS Person");
    
            // 创建表
            db.execSQL("CREATE TABLE Person ("
                    + "  id INTEGER PRIMARY KEY AUTOINCREMENT,"
                    + "  name varchar(30),"
                    + "  age SMALLINT"
                    + ")");
            Log.d(INFO, "Create Table Successful");
    
            Person person = new Person();
            person.name = "Tikitoo";
            person.age = 23;
            // 插入数据
            db.execSQL("INSERT INTO Person VALUES(NULL , ?, ?)", new Object[]{person.name, person.age});
            Log.d(INFO, "Insert Successful");
    
            person.name = "Davin";
            person.age = 30;
            ContentValues cv = new ContentValues();
            cv.put("name", person.name);
            cv.put("age", person.age);
            // 插入ContentValue 中的数据
            db.insert("Person", null, cv);
            Log.d(INFO, "ContentValues Insert Successful");
    
            cv = new ContentValues();
            cv.put("age", 35);
            // 更新数据
            db.update("Person", cv, "name = ?", new String[]{"Davin"});
            Log.d(INFO, "Update Successful");
    
            Cursor cursor = db.rawQuery("SELECT * FROM Person", null);
            while (cursor.moveToNext()) {
                int id = cursor.getInt(cursor.getColumnIndex("id"));
                String name = cursor.getString(cursor.getColumnIndex("name"));
                int age = cursor.getInt(cursor.getColumnIndex("age"));
                Log.d("INFO", id + name + age);
            }
            Log.d(INFO, "Query Successful");
    
            cursor.close();
    
            db.delete("Person", "age < ?", new String[]{"25"});
            Log.d(INFO, "Delete Successful");
    
            db.close();
    
            // deleteDatabase("tikitoo_sqlite.db");
        }
    }
    

    参考:

    Android SQLite Database Tutorial
    Android中SQLite应用详解 - scott's blog - 博客频道 - CSDN.NET

    问题总结

    使用SQLite 调试工具ADB(adb)

    (android:adb环境变量的配置)[http://blog.csdn.net/huangbiao86/article/details/6664779]
    使用ADB 工具查看adb shell

    cd data,ls 出现错误,这是,输入su 回车即可,会请求访问权限,在手机同意一下;
    adb opendir failed ,permission denied


    当然Android 对于SQLite 处理封装的对象 SQLiteOpenHelper 来返回 SQLiteDatabase 对象来实现增删改查
    我们再开发的时候,不能像上面写得那么简单,需要对封装一个子类,提供SQLiteOpenHelper 对象;

    封装的SQLiteOpenHelper 对象

    package com.tikitoo.android.sqlite.util;
    
    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    
    /**
     * Created by Tikitoo1 on 2014/11/12.
     */
    public class DBHelper extends SQLiteOpenHelper {
    
        private static final String DATABASE_NAME = "test.db";
        private static final int DATABASE_VERSION = 1;
    
        public DBHelper(Context context) {
            // 设置SQLiteDatabase.CursorFactory 为null
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }
    
        // 数据库第一次创建被调用
        @Override
        public void onCreate(SQLiteDatabase db) {
            // 初始化创建一个表
            db.execSQL("CREATE TABLE IF NOT EXISTS Person"
                    + "(id INTEGER PRIMARY KEY AUTOINCREMENT, name varchar(30), age  SMALLINT");
        }
    
        // 如果数据库版本改变,则会调用
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            // 新增一个字段
            db.execSQL("ALTER TABLE Person ADD COLUMN other STRING");
        }
    }
    

    DatabaseSQLite 对象实现对数据库的增删改查

    
    import android.content.ContentValues;
    import android.content.Context;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.util.Log;
    
    import java.util.ArrayList;
    import java.util.List;
    
    
    public class DBManager {
    
        private static final String INFO = DBManager.class.toString();
        private DBHelper helper;
        private SQLiteDatabase db;
    
        public DBManager(Context context) {
            helper = new DBHelper(context);
            db = helper.getWritableDatabase();
            // helper.getReadableDatabase();
        }
    
        // 新增一条数据,将数据存在Person 对象,在放在List 集合中,遍历集合,可以实现多条数据插入;
        public void add(List<Person> persons) {
            db.beginTransaction();
    
            try {
                for (Person person : persons) {
                    db.execSQL("INSERT INTO Person VALUES(NULL, ?, ?, ?)",
                            new Object[]{person.name, person.age, person.info});
                }
    
                // 设置事物
                db.setTransactionSuccessful();
            } finally {
                // 结束事物
                db.endTransaction();
            }
        }
    
        // 更新一条数据,通过name 来修改age
        public void update(Person person) {
            ContentValues cv = new ContentValues();
            cv.put("age", person.age);
            cv.put("info", person.info);
            // 参数,(表名, ContentValues 对象, where 条件,where 条件对应的值)
            db.update("Person",cv, "name = ?", new String[]{person.name});
        }
    
        public void delete(Person person) {
            db.delete("Person", "age >= ?", new String[]{"" + person.age});// String.valueOf(person.age);
        }
    
        public List<Person> person() {
            List<Person> lists = new ArrayList<Person>();
    
            // 使用rawQuery() 方法,返回游标对象,遍历出数据库的数据
            Cursor cursor = db.rawQuery("SELECT * FROM Person", null);
            while (cursor.moveToNext()) {
                int _id = cursor.getInt(cursor.getColumnIndex("id"));
                String name = cursor.getString(cursor.getColumnIndex("name"));
                int age = cursor.getInt(cursor.getColumnIndex("age"));
                String info = cursor.getString(cursor.getColumnIndex("info"));
    
                Log.i(INFO, new Person(_id, name, age, info).toString());
            }
            return lists;
        }
    
        // 关闭数据库
        public void closeDB() {
            db.close();
        }
    }
    

    对了还有将数据表使用JavaBean 处理,将数据存储在Person 对象,比较方便

    public class Person {
        public int _id;     // id,唯一标识
        public String name; // 姓名
        public int age;     // 年龄
        public String info; // 备注信息
    
        public Person() {
        }
    
        public Person(String name, int age, String info) {
            this.name = name;
            this.age = age;
            this.info = info;
        }
    
        public Person(int _id, String name, int age, String info) {
            this._id = _id;
            this.name = name;
            this.age = age;
            this.info = info;
        }
    
        // 重写toString() 方法
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("Person[ ");
            sb.append("name = " + this.name);
           // sb.append("; id = " + _id);
            sb.append("; age = " + this.age);
            sb.append("; info = " + this.info);
            sb.append(" ]");
            return sb.toString();
        }
    }
    

    getReadableDatabase() 和getWritableDatabase() 方法的区别:

    getReadableDatabase:

    首先判断数据库实例是否是打开状态,
    如果是,则打开一个可读写的数据库实例;
    如果遇到磁盘已满,获取失败,再以可读模式打开数据库,返回数据库实例

    getWritableDatabase:

    如果不为空,已经打开,并不是以只读模式打开的,
    如果mDatabase 不为空则加锁,然后创建或打开新的数据库实例,比较版本,为数据库设置新的版本号,最后把不为空的mDatabase 解锁,把新创建的数据库实例赋值给 mDatabase,并返回新的实例;

    总结

    所以,如果不遇到磁盘已满的情况下,两个方式返回的数据库实例是一样的,如果担心这种方式发生,先调用 getWritableDatabase 方法,
    如果异常,则在调用 getReadableDatabase ,当然这个时候的数据库实例是只读的

  • 相关阅读:
    多线程(一)初步使用
    数据迁移:MSSQL脚本文件过大,客户端没有足够的内存继续执行程序
    统计数据,数据库就只有8,9,10的,而前端需要返回连续的记录
    Windows10禁用update
    C#模拟HTTP POST 请求
    C#中Equals和= =(等于号)的比较(转)
    .net framework4与其client profile版本的区别
    centos7 安装mysql
    JAVA中使用ASN.1
    使用gradle建立java application
  • 原文地址:https://www.cnblogs.com/zhousysu/p/5483874.html
Copyright © 2020-2023  润新知