Android | SQLite的使用

2019-06-11 19:27:45 浏览数 (1)

核心:SQLiteOpenHelper帮助类(是一个抽象类)

借助这个类就可以非常简单地对数据库进行创建和升级;

创建数据库

  • SQLiteOpenHelper是抽象类,需创建自己的类继承;
  • 其中有两个抽象方法, onCreate()onUpgrade(), 需重写,实现创建升级数据库的逻辑。
  • 还有两个重要的实例方法: getReadableDatabase()getWritableDatabase()。 都可创建打开现有数据库(数据库已经存在则直接打开,没有则创建), 并返回可对数据库进行读写操作的对象。 其不同:当数据库不可写入时(如磁盘空间已满)前者返回的对象以getReadableDatabase()打开数据库,getWritableDatabase()将出现异常
  • SQLiteOpenHelper有两个构造方法可供重写, 一般使用参数少一点的那个构造方法, 其接收四个参数: Context数据库名,创建数据库时使用的就是这里指定的名称允许查询数据时返回一个自定义的Cursor(一般传入null), 当前数据库版本号(用于升级操作)。

构建SQLiteOpenHelper实例后, 再调用他的getReadableDatabase()/getWritableDatabase()方法就能创建数据库 (数据库文件会存放在/data/data/<package name>/databases/目录下)。 此时重写的onCreate()方法被执行(通常处理创建表的逻辑)。!!!!!!

示例代码

创建名为BookStore.db的数据库,并新建一张Book表。 新建MyDatabaseHelper类继承自SQLiteOpenHelper

代码语言:javascript复制
public class MyDatabaseHelper extends SQLiteOpenHelper {
    //将见表语句定义成字符串常量
    public  static final String CREATE_BOOK = "create table Book ("
              "id integer primary key autoincrement, "
              "author text, "
              "price real, "
              "pages integer, "
              "name text)" ;
    private Context mContext;

    public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        mContext = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        //在数据库创建完成时创建Book表
        db.execSQL(CREATE_BOOK);
        Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

注意autoincrement表示id是自增长的;

使用MyDatabaseHelper创建数据库
代码语言:javascript复制
public class MainActivity extends AppCompatActivity {
    private MyDatabaseHelper dbhelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //构建SQLiteOpenHelper实例
        dbhelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);

        Button createDatabase = (Button) findViewById(R.id.create_database);
        createDatabase.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //调用SQLiteOpenHelper实例的getReadableDatabase()/getWritableDatabase()方法
              //就能创建数据库了
              //此时重写的onCreate()方法被执行
              //如以上所写,则创建了Book表
                dbhelper.getWritableDatabase();
            }
        });
    }
}

升级(更新)数据库

基于以上代码, 再添加一张Category表用于记录图书分类, 在继承自SQLiteOpenHelperMyDatabaseHelper类中添加代码: (添加的地方以感叹号标记,一共四处)

代码语言:javascript复制
public class MyDatabaseHelper extends SQLiteOpenHelper {
    //将见表语句定义成字符串常量
    public  static final String CREATE_BOOK = "create table Book ("
              "id integer primary key autoincrement, "
              "author text, "
              "price real, "
              "pages integer, "
              "name text)" ;
    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1.
    public static final String CREATE_CATEGORY = "create table Category ("
              "id integer primary key autoincrement, "
              "category_name text, "
              "category_code integer)";**

    private Context mContext;

    public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        mContext = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        //在数据库创建完成时创建Book表
        db.execSQL(CREATE_BOOK);

        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2.
        db.execSQL(CREATE_CATEGORY);
        Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {    
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 3.
        db.execSQL("drop table if exists Book");
        db.execSQL("drop table if exists Category");
        onCreate(db); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 4.

    }
}

再次调用getWritableDatabase();时, onCreate()不会再执行了, 因为数据库只能创建一次,刚刚已经创建过了; 所以这里只能在onUpgrade()中, 执行Drop将原来的表删掉, 再重新调用onCreate()方法, 这样一开始的表新加的表都会被创建;

调用onUpgrade()

构造SQLiteOpenHelper实例的时候, 第四个参数(version)传入大于旧版本的数字 即可让onUpgrade()执行,进而更新数据库:

代码语言:javascript复制
public class MainActivity extends AppCompatActivity {
    private MyDatabaseHelper dbhelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        dbhelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        Button createDatabase = (Button) findViewById(R.id.create_database);
        createDatabase.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dbhelper.getWritableDatabase();
            }
        });
    }
}

CRUD核心: getReadableDatabase()getWritableDatabase()返回的SQLiteDatabase对象; 在Android中即使不去编写SQL语句, 提供了一系列辅助性方法, 也能轻松完成所有CRUD操作。 SQLiteOpenHelper的两个实例方法getReadableDatabase()/getWritableDatabase() 会返回SQLiteDatabase对象, 借助这个对象就可对数据进行CRUD操作。

添加数据

首先调用ContentValues实例的各种重载的put(表的某个属性,值)方法, 向ContentValues实例自身中添加数据; 接着调用insert()即可将数据加到对应的表中; 它接收三个参数:

  1. 表名,指定向哪张表添加数据;
  2. 用于在未指定添加数据的情况下, 给某些可为空的列自动复赋值NULL, 一般用不到这个功能, 直接传入NULL即可;
  3. ContentValues实例;
代码语言:javascript复制
public class MainActivity extends AppCompatActivity {
    private MyDatabaseHelper dbhelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        dbhelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
        Button createDatabase = ...

        Button addData = (Button) findViewById(R.id.add_data);
        addData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbhelper.getWritableDatabase();
               
                ContentValues values = new ContentValues();

                //开始组装第一条数据
                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.put("name", "The Lost Symbol");
                values.put("author", "Dan Brown");
                values.put("pages",510);
                values.put("price", 19.95);
                db.insert("Book",null,values);//插入第二条数据
            }
        });
        ...

更新数据

  1. 首先调用ContentValues实例的各种重载的put(表的某个属性,值)方法,
  2. 接着调用update()实现更新—— 第三、四个参数用于约束更新某一行或某几行数据, 默认更新所有行; 第三个参数对应SQL的where语句,占位符, 通过第四个参数提供的字符串数组指定相应内容; 第一参数表名,第二参数ContentValues实例;
代码语言:javascript复制
 Button updateData = (Button) findViewById(R.id.update_data);
        updateData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbhelper.getWritableDatabase();
                ContentValues values = new ContentValues();
                values.put("price", 10.99);
                db.update("Book",values, "name = ?", new String[]{"The Da Vinci Code"});
            }
        });

上述代码表达的意图将name为The Da Vinci Code的这本书的价格改成10.99;

删除数据

  • 直接用SQLiteDatabase实例调用delete(); 其第一参,表明; 二三参,同update()的三四参;
代码语言:javascript复制
 Button button = (Button) findViewById(R.id.delete_data);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbhelper.getWritableDatabase();
                db.delete("Book", "pages > ?", new String[]{"500"});
            }
        });

查询数据

  • 通过query()进行查询; 其重载方法多,参数复杂, 我们看参数最少(7个参数)的一个; 参数对应内容可参考下表: (其三四参,同update()的三四参;)
  • query()参数多, 但是多数情况不必要全部参数都用, 指定少数几个参数即可完成查询 (如只传入第一个参数表名, 后面全为null,则查询表中的所有数据); 调用query()后会返回一个Cursor(n.光标)对象, 查询到的所有数据都将从这个对象中取出

示例代码:

代码语言:javascript复制
Button queryButton = (Button) findViewById(R.id.query_data);
        queryButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbhelper.getWritableDatabase();
                //查询Book表中所有数据
                Cursor cursor = db.query("Book", null,null,null,null,null,null);
                if (cursor.moveToFirst()){
                    do {
                        //遍历Cursor对象,取出数据并打印
                        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("MainActivity", "book name is "   name);
                        Log.d("MainActivity", "book author is "   author);
                        Log.d("MainActivity", "book pages is "   pages);
                        Log.d("MainActivity", "book price is "   price);
                    }while (cursor.moveToNext());
                }
                cursor.close();
            }
        });

Cursor实例每次指向返回数据表的一行, 通过moveToFirst()moveToNext()等方法来调节其指向的位置; 令其指向某一行,或者一行一行遍历返回的数据表, 对返回的数据进行处理即可。

0 人点赞