美文网首页数据库知识
数据存储与访问之——SQLite数据库

数据存储与访问之——SQLite数据库

作者: JuSong | 来源:发表于2017-03-02 11:48 被阅读0次

    SQLite数据库,和其他的SQL数据库不同, 我们并不需要在手机上另外安装一个数据库软件,Android系统已经集成了这个数据库。

    SQLite有什么特点

    SQlite通过文件来保存数据库,一个文件就是一个数据库,数据库中又包含多个表格,表格里又有 多条记录,每个记录由多个字段构成,每个字段有对应的,每个值我们可以指定类型,也可以不指定 类型(主键除外)

    为什么要用SQLite:

    SP是一种轻量级数据存储方式,存储一些跟账号密码个人信息相关的数据,如果数据繁杂这时候就要用到SQLite存储以提高数据存取得效率。

    几个相关的类:

    SQLiteOpenHelper

    :抽象类,我们通过继承该类,然后重写数据库创建以及更新的方法, 我们还可以通过该类的对象获得数据库实例,或者关闭数据库!

    SQLiteDatabase:数据库访问类:我们可以通过该类的对象来对数据库做一些增删改查的操作

    Cursor:游标,有点类似于JDBC里的resultset,结果集!可以简单理解为指向数据库中某 一个记录的指针!可以通过Cursor对数据进行一行一行查询的操作

     

    使用SQLiteOpenHelper类创建数据库与版本管理

    安卓给我们提供了SQLiteOpenHelper的两个方法, onCreate( )与onUpgrade( )来实现

    onCreate(database)

    :首次使用软件时生成数据库表

    onUpgrade(database,oldVersion,newVersion)

    :在数据库的版本发生变化时会被调用, 一般在软件升级时才需改变版本号,而数据库的版本是由程序员控制的,假设数据库现在的 版本是1,由于业务的变更,修改了数据库表结构,这时候就需要升级软件,升级软件时希望 更新用户手机里的数据库表结构,为了实现这一目的,可以把原来的数据库版本设置为2 或者其他与旧版本号不同的数字即可!

     

     

    public class MyDBOpenHelper extends SQLiteOpenHelper {
    public MyDBOpenHelper(Context context, String name, CursorFactory factory,
    int version) {super(context, "my.db", null, 1); }
    @Override
    //数据库第一次创建时被调用
    public void onCreate(SQLiteDatabase db) {
    db.execSQL("CREATE TABLE person(personid INTEGER PRIMARY KEY AUTOINCREMENT,name VARCHAR(20))");

    }
    //软件版本号发生改变时调用
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("ALTER TABLE person ADD phone VARCHAR(12) NULL");
    }
    }

     

    我们会创建这个my.db的文件,并且会执行onCreate()里的方法, 创建一个Person的表,他又两个字段,主键personId和name字段;接着如我我们修改db的版本 号,那么下次启动就会调用onUpgrade()里的方法,往表中再插入一个字段!另外这里是插入 一个字段,所以数据不会丢失,如果是重建表的话,表中的数据会全部丢失(下面数据库更新解决)

     

    流程:

    Step 1:自定义一个类继承SQLiteOpenHelper类

    Step 2:在该类的构造方法的super中设置好要创建的数据库名,版本号

    Step 3:重写onCreate( )方法创建表结构

    Step 4:重写onUpgrade( )方法定义版本号发生改变后执行的操作

    使用Android提供的API操作SQLite

     

    db = myDBHelper.getWritableDatabase();
    switch (v.getId()) {
    case R.id.btn_insert:
    ContentValues values1 = new ContentValues();
    values1.put("name", "呵呵~" + i);
    i++;
    //参数依次是:表名,强行插入null值得数据列的列名,一行记录的数据
    db.insert("person", null, values1);
    Toast.makeText(mContext, "插入完毕~", Toast.LENGTH_SHORT).show();
    break;
    case R.id.btn_query:
    sb = new StringBuilder();
    //参数依次是:表名,列名,where约束条件,where中占位符提供具体的值,指定group by的列,进一步约束
    //指定查询结果的排序方式
    Cursor cursor = db.query("person", null, null, null, null, null, null);
    if (cursor.moveToFirst()) {
    do {
    int pid = cursor.getInt(cursor.getColumnIndex("personid"));
    String name = cursor.getString(cursor.getColumnIndex("name"));
    sb.append("id:" + pid + ":" + name + "\n");
    } while (cursor.moveToNext());
    }
    cursor.close();
    Toast.makeText(mContext, sb.toString(), Toast.LENGTH_SHORT).show();
    break;
    case R.id.btn_update:
    ContentValues values2 = new ContentValues();
    values2.put("name", "嘻嘻~");
    //参数依次是表名,修改后的值,where条件,以及约束,如果不指定三四两个参数,会更改所有行
    db.update("person", values2, "name = ?", new String[]{"呵呵~2"});
    break;
    case R.id.btn_delete:
    //参数依次是表名,以及where条件与约束
    db.delete("person", "personid = ?", new String[]{"3"});
    break;
    }

     

     

    使用SQL语句操作数据库

     

    不想用Android提供的这些API, 你可以直接使用SQLiteDatabase给我们提供的相关方法:

    execSQL(SQL,Object[]):使用带占位符的SQL语句,这个是执行修改数据库内容的sql语句用的

    rawQuery(SQL,Object[]):使用带占位符的SQL查询操作 另外前面忘了介绍下Curosr这个东西以及相关属性,这里补充下: ——

    Cursor:对象有点类似于JDBC中的ResultSet,结果集!使用差不多,提供一下方法移动查询结果的记录指针:

    move(offset):指定向上或者向下移动的行数,整数表示向下移动;负数表示向上移动!

    moveToFirst():指针移动到第一行,成功返回true,也说明有数据

    moveToLast():指针移动到最后一样,成功返回true;

    moveToNext():指针移动到下一行,成功返回true,表明还有元素!

    moveToPrevious():移动到上一条记录

    getCount( )获得总得数据条数

    isFirst():是否为第一条记录

    isLast():是否为最后一项

    moveToPosition(int):移动到指定行

    使用代码示例:

    //插入数据
    public void save(Customer customer){
    SQLiteDatabase sqLiteDatabase=dbHelper.getWritableDatabase();
    sqLiteDatabase.execSQL("INSERT INTO customer(customerName,deliveryPhone) values(?,?)",new String[]{customer.getCustomerName(),customer.getDeliveryPhone()});
    }
    //删除数据
    public void delete(Integer customerid){
    SQLiteDatabase sqLiteDatabase=dbHelper.getWritableDatabase();
    sqLiteDatabase.execSQL("DELETE FROM customer WHERE customerid=?",new Integer[]{customerid});
    }

    //更新数据
    public void updata(Customer customer){
    SQLiteDatabase sqLiteDatabase=dbHelper.getWritableDatabase();
    sqLiteDatabase.execSQL("UPDATA customer SET customerName=?,deliveryPhone=? WHERE customerid=?",new String[]{customer.getCustomerName(),customer.getDeliveryPhone(), String.valueOf(customer.getCustomerId())});
    }
    //查询数据

    public Customer select(Integer customerid){
    SQLiteDatabase sqLiteDatabase=dbHelper.getReadableDatabase();
    Cursor cursor=sqLiteDatabase.rawQuery("SELECT * FROM customer WHERE customerid=?",new String[]{customerid.toString()});
    //存在数据才返回true
    if(cursor.moveToFirst()){
    int id=cursor.getInt(cursor.getColumnIndex("customerid"));
    String name=cursor.getString(cursor.getColumnIndex("customerName"));
    String phone=cursor.getString(cursor.getColumnIndex("deliveryPhone"));
    return new Customer(id,name,phone);
    }
    cursor.close();
    return null;
    }
    //.数据分页查询
    public List<Customer> getScrollData(int offset, int maxResult)
    {
    List<Customer> person = new ArrayList<Customer>();
    SQLiteDatabase db = dbHelper.getReadableDatabase();
    Cursor cursor = db.rawQuery("SELECT * FROM person ORDER BY personid ASC LIMIT= ?,?",
    new String[]{String.valueOf(offset),String.valueOf(maxResult)});
    while(cursor.moveToNext())
    {
    int id = cursor.getInt(cursor.getColumnIndex("personid"));
    String name = cursor.getString(cursor.getColumnIndex("name"));
    String phone = cursor.getString(cursor.getColumnIndex("phone"));
    person.add(new Customer(id,name,phone)) ;
    }
    cursor.close();
    return person;
    }
    //查询记录数
    public long getCount()
    {
    SQLiteDatabase db = dbHelper.getReadableDatabase();
    Cursor cursor = db.rawQuery("SELECT COUNT (*) FROM customer",null);
    cursor.moveToFirst();
    long result = cursor.getLong(0);
    cursor.close();
    return result;
    }

     

    除了上面获取条数的方法外还可以使用cursor.getCount()方法获得数据的条数, 但是SQL语句要改改!比如SELECT * FROM customer;

     

    SQLite事务

    多个操作捆绑在一起,只有所有操作都执行完毕,事务才会生效,如果其中有一个操作未执行完毕,之前所有操作都会撤销。

     

    方法:

    beginTransaction():开启事务

    endTransaction():结束事务

    setTransactionSuccessful():结束事务有两张方式,事务回滚或者事务 提交,默认为false撤销,如果提交设置为true.

    简单点说就是:写在事务里的所有数据库操作都成功,事务提交,否则,事务回滚到原始状态

    SQLite存储大二进制文件

    一般我们很少往数据库中存储大二进制文件,比如图片,音频,视频等,对于这些我们一般 是存储文件路径,但总会有些奇葩的需求。以图片为例子,将图片保存到SQLite中,以及读取SQLite中的图片!

     

    1.保存图片到Sqlite中:

    (1)创建数据库表的时候,需要创建一个BLOB的字段,用于存储二进制值。

    sqLiteDatabase.execSQL("CREATE TABLE test(_id INTEGER PRIMARY KEY AUTOINCREAMENT,head_img BLOB)");

    (2)将图片转换成BLOB格式(这里是ImageView为例,如果是普通图片只需要转换成Bitmap再调用即可)

    try {
    SQLiteDatabase sqLiteDatabase=dbHelper.getWritableDatabase();
    ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
    //压缩为PNG格式,100标示跟原图大小一致
    (BitmapDrawable)imageView.getDrawable().getBitmap().compress(Bitmap.CompressFormat.PNG,100,byteArrayOutputStream);
    Object[] objects=new Object[]{byteArrayOutputStream.toByteArray()};
    sqLiteDatabase.execSQL("INSERT INTO test(head_img) values(?)",objects);
    byteArrayOutputStream.close();
    sqLiteDatabase.close();
    } catch (IOException e) {
    e.printStackTrace();
    }

     

    读取SQLite中的图片

    //读取SQLIte中的图片
    SQLiteDatabase sqLiteDatabase=dbHelper.getReadableDatabase();
    Cursor cursor=sqLiteDatabase.rawQuery("SELECT head_img FROM text",null);
    if(cursor!=null){
    if(cursor.moveToFirst()){
    //取出图片保存到字节数组中
    byte[] img=cursor.getBlob(cursor.getColumnIndex("head_img"));
    //将图片显示到Imageview上面
    if(img!=null){
    ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(img);
    imageView.setImageDrawable(Drawable.createFromStream(byteArrayInputStream,"img"));
    }
    }
    cursor.close();
    }

     

    数据库升级

    假如我们已经升级到第三个版本了,我们在第二个版本增加了一个表,

    然后第三个版本也增加了一个表,加入用户直接从第一个版本升级到第三个版本,这样

    没经过第二个版本,就没有增加的那个表,这可怎么破?

     

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

    private void upgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (newVersion > oldVersion) {
    if (oldVersion + 1 == newVersion) {
    switch (oldVersion) {
    case 1:
    upgrade1_2(db);
    break;
    case 2:
    upgrade2_3(db);
    break;
    case 3:
    upgrade3_4(db);
    case 4:
    upgrade4_5(db);
    case 5:
    upgrade5_6(db);
    case 6:
    upgrade6_7(db);
    case 7:
    upgrade7_8(db);
    case 8:
    upgrade8_9(db);
    default:
    break;
    }
    return;
    }
    upgrade(db, oldVersion, newVersion - 1);
    upgrade(db, newVersion - 1, newVersion);
    }
    }

    private void upgrade1_2(SQLiteDatabase db) {
    String sql = "drop table storage;";
    db.execSQL(sql);
    db.execSQL(storageSQL);
    }

    相关文章

      网友评论

        本文标题:数据存储与访问之——SQLite数据库

        本文链接:https://www.haomeiwen.com/subject/iajhgttx.html