【Android -- 数据存储】使用 SQLite 存储数据

在这里插入图片描述

一、前言

在 Android 中一共提供了五种数据存储方式,分别为:
1. Files:通过FileInputStream和FileOutputStream对文件进行操作。具体使用方法可以参阅博文《Android学习笔记34:使用文件存储数据》。

2. Shared Preferences:常用来存储键值对形式的数据,对系统配置信息进行保存。

3. Content Providers:数据共享,用于应用程序之间数据的访问。

4. SQLite:Android自带的轻量级关系型数据库,支持SQL语言,用来存储大量的数据,并且能够对数据进行使用、更新、维护等操作。

5. Network:通过网络来存储和获取数据。

本篇博文主要介绍第一种方式,通过 SQLite 存储数据。

二、实战

在项目开发中,我们或多或少都会用到数据库。在 Android 中,我们一般使用 SQLite,因为 Android 在 android.database.sqlite 包封装了很多 SQLite 操作的 API。
在这里插入图片描述
在使用 SQLite 时,我建议先下载一个本地 SQLite 客户端来验证操作,在本地写的 SQL 语句运行正确后,再转移到 Android 中。我用的是 SQLite Expert Personal

1. 创建一个继承在 SQLiteOpenHelper 的类,并重写 onCreate() 和 onUpgrade() 方法。

public class OrderDBHelper extends SQLiteOpenHelper{
    
    
    private static final int DB_VERSION = 1;
    private static final String DB_NAME = "myTest.db";
    public static final String TABLE_NAME = "Orders";

    public OrderDBHelper(Context context) {
    
    
        super(context, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
    
    
        // create table Orders(Id integer primary key, CustomName text, OrderPrice integer, Country text);
        String sql = "create table if not exists " + TABLE_NAME + " (Id integer primary key, CustomName text, OrderPrice integer, Country text)";
        sqLiteDatabase.execSQL(sql);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
    
    
        String sql = "DROP TABLE IF EXISTS " + TABLE_NAME;
        sqLiteDatabase.execSQL(sql);
        onCreate(sqLiteDatabase);
    }
}

这个类主要用于建数据库和建表用,我们再创建一个 OrderDao 用于处理所有的数据操作方法。在 OrderDao 中实例化OrderDBHelper:

public OrderDao(Context context) {
    
    
    this.context = context;
    ordersDBHelper = new OrderDBHelper(context);
}

数据库操作无外乎:“增删查改”。对于“增删改”这类对表内容变换的操作,我们需先调用 getWritableDatabase() ,在执行的时候可以调用通用的 execSQL(String sql) 方法或对应的操作 API:insert()、delete()、update() 。而对“查”,需要调用 getReadableDatabase() ,这时就不能使用 execSQL 方法了,得使用 query() 或 rawQuery() 方法。

增加数据

  • 初始化数据
    在进入 Demo 程序时,先判断表中是否有数据,如果表中没有数据,先添加一些数据。在初始化数据时,因为一次性要添加的数据比较多,所以直接采用的是 execSQL 方法:
db = ordersDBHelper.getWritableDatabase();
db.beginTransaction();

db.execSQL("insert into " + OrderDBHelper.TABLE_NAME + " (Id, CustomName, OrderPrice, Country) values (1, 'Arc', 100, 'China')");
db.execSQL("insert into " + OrderDBHelper.TABLE_NAME + " (Id, CustomName, OrderPrice, Country) values (2, 'Bor', 200, 'USA')");
db.execSQL("insert into " + OrderDBHelper.TABLE_NAME + " (Id, CustomName, OrderPrice, Country) values (3, 'Cut', 500, 'Japan')");
db.execSQL("insert into " + OrderDBHelper.TABLE_NAME + " (Id, CustomName, OrderPrice, Country) values (4, 'Bor', 300, 'USA')");
db.execSQL("insert into " + OrderDBHelper.TABLE_NAME + " (Id, CustomName, OrderPrice, Country) values (5, 'Arc', 600, 'China')");
db.execSQL("insert into " + OrderDBHelper.TABLE_NAME + " (Id, CustomName, OrderPrice, Country) values (6, 'Doom', 200, 'China')");

db.setTransactionSuccessful();
  • 插入一条新数据
    我们还可以使用 insert(String table,String nullColumnHack,ContentValues values) 方法来插入,ContentValues 内部实现就是HashMap,但是两者还是有差别的,ContenValues Key 只能是 String 类型,Value 只能存储基本类型的数据,像 string,int 之类的,不能存储对象这种东西:
public ContentValues() {
    
    
    // Choosing a default size of 8 based on analysis of typical
    // consumption by applications.
    mValues = new HashMap<String, Object>(8);
}

使用 insert() 方法我们插入一条新数据(7, “Jne”, 700, “China”),对于修改数据的操作我们一般当作事务(Transaction)处理:

db = ordersDBHelper.getWritableDatabase();
db.beginTransaction();

// insert into Orders(Id, CustomName, OrderPrice, Country) values (7, "Jne", 700, "China");
ContentValues contentValues = new ContentValues();
contentValues.put("Id", 7);
contentValues.put("CustomName", "Jne");
contentValues.put("OrderPrice", 700);
contentValues.put("Country", "China");
db.insertOrThrow(OrderDBHelper.TABLE_NAME, null, contentValues);

db.setTransactionSuccessful();

删除数据

删除数据的方法除了 execSQL 还有 delete(String table,String whereClause,String[] whereArgs),whereClause是删除条件,whereArgs 是删除条件值数组。

db = ordersDBHelper.getWritableDatabase();
db.beginTransaction();

// delete from Orders where Id = 7
db.delete(OrderDBHelper.TABLE_NAME, "Id = ?", new String[]{
    
    String.valueOf(7)});
db.setTransactionSuccessful();

再看删除的源码,里面会拼装删除条件和删除条件值数组:

public int delete(String table, String whereClause, String[] whereArgs) {
    
    
    acquireReference();
    try {
    
    
        SQLiteStatement statement =  new SQLiteStatement(this, "DELETE FROM " + table +
                (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
        try {
    
    
            return statement.executeUpdateDelete();
        } finally {
    
    
            statement.close();
        }
    } finally {
    
    
        releaseReference();
    }
}

修改数据
修改数据和插入数据很相似,调用的方法除了execSQL还可以是 update(String table,ContentValues values,String whereClause, String[] whereArgs)

db = ordersDBHelper.getWritableDatabase();
db.beginTransaction();

// update Orders set OrderPrice = 800 where Id = 6
ContentValues cv = new ContentValues();
cv.put("OrderPrice", 800);
db.update(OrderDBHelper.TABLE_NAME,
        cv,
        "Id = ?",
        new String[]{
    
    String.valueOf(6)});
db.setTransactionSuccessful();

查找数据
查找数据有两个方法,一是 public Cursor query(String table,String[] columns,String selection,String[] selectionArgs,String groupBy,String having,String orderBy,String limit);,另外一个是 public Cursor rawQuery(String sql, String[] selectionArgs)。rawQuery的写法类似上面的execSQL,在此不做介绍,query方法中的参数如下:

  • table:表名称
  • columns:列名称数组
  • selection:条件字句,相当于where
  • selectionArgs:条件字句,参数数组
  • groupBy:分组列
  • having:分组条件
  • orderBy:排序列
  • limit:分页查询限制
  • Cursor:返回值,相当于结果集ResultSet

我们可以看到返回的类型都是 Cursor,Cursor是一个游标接口,提供了遍历查询结果的方法,如移动指针方法move(),获得列值方法。Cursor 游标常用方法如下:
在这里插入图片描述
我们先来查一查用户名为"Bor"的信息:

db = ordersDBHelper.getReadableDatabase();

// select * from Orders where CustomName = 'Bor'
cursor = db.query(OrderDBHelper.TABLE_NAME,
        ORDER_COLUMNS,
        "CustomName = ?",
        new String[] {
    
    "Bor"},
        null, null, null);

if (cursor.getCount() > 0) {
    
    
    List<Order> orderList = new ArrayList<Order>(cursor.getCount());
    while (cursor.moveToNext()) {
    
    
        Order order = parseOrder(cursor);
        orderList.add(order);
    }
    return orderList;
}

当然我们也可以查询总数、最大值最小值之类的,以查询Country为China的用户总数为例:

db = ordersDBHelper.getReadableDatabase();
// select count(Id) from Orders where Country = 'China'
cursor = db.query(OrderDBHelper.TABLE_NAME,
        new String[]{
    
    "COUNT(Id)"},
        "Country = ?",
        new String[] {
    
    "China"},
        null, null, null);

if (cursor.moveToFirst()) {
    
    
    count = cursor.getInt(0);
}

猜你喜欢

转载自blog.csdn.net/duoduo_11011/article/details/125604085