• 主页
  • 归档
  • 标签
  • 关于

  • 主页
  • 归档
  • 标签
  • 关于

Android & SQLite 简易入门

2020-02-11

这是一个最最最基础的在 Android 开发中使用本地 SQLite 的介绍,仅仅包括最基本的连接和增删改查(就够基本用= =)。其实Android 官方推荐使用更有效率的 Room数据库 来存储数据,不过 SQLite 更为常用。在学习的时候发现网上的中文教程实在是比较。。。一言难尽,而我又需要讲的比较仔细,因此就决定自己写一份,就给我这样的新(cai)手(ji)做个参考叭。

驱动

SQLite 不需要任何驱动!!!不需要下载任何东西,直接上代码就行。(我真的有读到让下载驱动的教程= =)

定义数据库

Android 提供 BaseColumns 接口将数据库内容(表名、列名)设定为全局变量。你 不一定 要使用它提供的接口,你可以把你的数据库设定写在任何地方,或者直接写建立数据库的 SQL 语句。不过使用 BaseColumns 可以让数据库更好的兼容 Android 体系,并且给数据库提供一个自增主键 _ID,类型为 long。具体使用方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public final class Database {
// 构造器设定为 private 防止意外调用
private Database() {}

// classes 数据表
public static class Classes implements BaseColumns {
public static final String TABLE_NAME = "classes";
public static final String COLUMN_NAME = "name";
public static final String COLUMN_DAY = "day";
}

// students 数据表
public static class Students implements BaseColumns {
public static final String TABLE_NAME = "students";
public static final String COLUMN_NAME = "name";
public static final String COLUMN_MAJOR = "major";
}
}

数据库 Helper

Android 官方提供了调用 SQLite 的 API SQLiteOpenHelper。我们只需要写一个包含数据库创建和版本信息的类来继承它,并在需要数据库的时候调用我们写的类就可以了。

关于如何填入数据库创建和版本信息,直接上代码叭

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public class DBHelper extends SQLiteOpenHelper {
// 每一次修改数据库中表时须要给版本号加一
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "college.db";

/**
* 构造器需要数据库的基本信息,即,新建的 helper 对象调用哪个数据库的哪个版本
* 这里将数据库名和版本号写在 helper类里
* 如果需要调用不同数据库不同版本,可以将数据库名和版本号作为构造器参数传入
* 第三个参数是 SQLiteDatabase.CursorFactory,用于生成 cursor,一般为 null(即使用默认形式)
**/
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

/**
* 这里是建立数据库的地方
* 这里传入的数据库参数就是构造器里传入的数据库名字对应的数据库(Android 自动调用)
* 第一次调用该数据库的时候将会执行这段代码,给数据库建立对应的表
**/
@Override
public void onCreate(SQLiteDatabase db) {

// 创建数据库的语句可以写在任何地方,不过方便起见暂时写在这里
// _ID 是之前用来管理数据表的 BaseColumns 接口提供的,不需要 autoincrement 就可以自增
// 写 SQL 语句时要注意空格
private static final String SQL_CREATE_CLASSES =
"CREATE TABLE " + Database.Classes.TABLE_NAME + " (" +
Database.Classes._ID + " INTEGER PRIMARY KEY," +
Database.Classes.COLUMN_NAME + " TEXT," +
Database.Classes.COLUMN_DAY + " INTEGER)";

private static final String SQL_CREATE_STUDENTS =
"CREATE TABLE " + Database.Students.TABLE_NAME + " (" +
Database.Students._ID + " INTEGER PRIMARY KEY," +
Database.Students.COLUMN_NAME + " TEXT," +
Database.Students.COLUMN_MAJOR+ " TEXT)";

// 执行创建数据库的sql语句
db.execSQL(classes);
db.execSQL(students);

}

/**
* 这是数据库升级的地方
* 这里传入的数据库参数也是构造器里传入的数据库名字对应的数据库(Android 自动调用)
**/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 由于这里的数据库只是本地缓存,所以升级暂时就就简单的删除再重建
private static final String SQL_DELETE_CLASSES =
"DROP TABLE IF EXISTS " + Database.Classes.TABLE_NAME;
private static final String SQL_DELETE_STUDENTS =
"DROP TABLE IF EXISTS " + Database.Students.TABLE_NAME;

db.execSQL(SQL_DELETE_CLASSES);
db.execSQL(SQL_DELETE_STUDENTS);
onCreate(db);
}
}

读写

读写数据库的时候,我们需要建立一个 DBhelper(即前面写的继承 SQLiteOpenHelper 类)的实例,并调用 getWritableDatabase() 或者 getReadableDatabase() 来获得所需的数据库。

1
2
3
// 传入 context,如果需要,同时传入数据库名称、版本号等
// 如果在 activity 中调用,则传入 context 的地方直接传入 this
DBHelper helper = new DBHelper(getContetx());

Android 官方小贴士:由于获取数据库信息需要花费较长时间,建议把获得读/写数据库以及读写数据库操作放在后台运行,比如放在 AsyncTask 或者 IntentService 中.

读

首先通过 hepler 来获得数据库,然后调用数据库的 query() 函数来获得数据。query() 函数会返回一个存储着数据的 cursor (类似于一个 Iterator 里面存 Map)。假设我们需要在 classes 表里获得第一天按 id 排的前五节课的 id 和课名(SELECT id, name FROM classes WHERE day =3 ORDER BY id DESC LIMIT 5)代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 通过 helper 获得一个只读数据库
SQLiteDatabase college = helper.getReadableDatabase();

// 调用数据库的 query 函数
/*
第一个参数:表名
第二个参数:所有需要选定的列,用字符串数组传入,若需要所有的则可以为 null
第三个参数:条件,SQL 语句 while 部分,参数的值可以用 ?代替(防止 SQL 注入),没有为 null
第四个参数:将参数填入前面的语句,用字符串数组传入,和前面的 ?一一对应,没有为 null
第五个参数:group by,SQL 语句 'GROUP BY' 部分,没有则为 null
第六个参数:having, SQL 语句 'HAVING' 的部分,没有则为 null
第七个参数:order by,SQL 语句 'ORDER BY' 的部分,没有则为 null
第八个参数:limit,SQL 语句 'LIMIT' 的部分,没有则为 null
*/
Cursor cursor = db.query(
Database.Classes.TABLE_NAME,
new String[]{Database.Classes._ID, Database.Classes.COLUMN_NAME},
Database.Classes.COLUMN_DAY + " = ?",
new String[]{"3"},
null,
null,
Database.Classes._ID + " DESC",
"5");

// 从 cursor 中获取信息,并储存在一个队列的 map 中
// 用 cursor.getColumnIndexOrThrow() 获取列对应的序号(序号其实是按照选择时的顺序从 0 开始)
// 用 cursor.getString() 等通过序号获取内容
List<Map<String, Object>> views = new ArrayList<>();
while (cursor.moveToNext()) {
Map<String, Object> m = new HashMap<>();
m.put("text1", cursor.getLong(cursor.getColumnIndexOrThrow(Database.Classes._ID)));
m.put("text2", cursor.getString(cursor.getColumnIndexOrThrow(Database.Classes.COLUMN_NAME)));
views.add(m);
}
cursor.close();

写

一样通过 hepler 来获得数据库,然后调用数据库的 insert() 函数将数据插入数据库。insert() 函数会返回当前插入数据的主键。假设我们需要在 classes 表里插入 name 为 OOP,在第三天上课的课程信息(INSERT INTO classes (name, day) VALUES (OOP, 3))并获得插入数据的 id,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 通过 helper 获得可写入的数据库
SQLiteDatabase db = dbHelper.getWritableDatabase();

// 将数据加入 ContentValues 中
// ContentValues 用法和 m、Map 类似,第一个参数 key 这里填列名,第二个参数填对应的值
ContentValues classes = new ContentValues();
classes.put(Database.Classes.COLUMN_NAME, "OOP");
classes.put(Database.Classes.COLUMN_DAY, 3);

// 这里在数据库里加入新的一行
/*
第一个参数:表名
第二个参数:所有可为空的列的名称,用于加入空行
第三个参数:包含列名和对应值的 ContentValues
*/
long i = db.insert(Database.Classes.TABLE_NAME, null, classes);

update() 和 insert() 类似,不过返回的数值是这次改动影响的行数。假设我们需要将 id 为 1 的课改名为 OOD (UPDATE classes SET name = OOD WHERE id = 1),代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 通过 helper 获得可写入的数据库
SQLiteDatabase db = dbHelper.getWritableDatabase();

// 将数据加入 ContentValues 中
ContentValues updates = new ContentValues();
updates.put(Database.Classes.COLUMN_NAME, "OOD");

// 这里在数据库里做修改
/*
第一个参数:表名
第二个参数:包含列名和对应值的 ContentValues
第三个参数:条件,SQL 语句 while 部分,参数的值可以用 ?代替(防止 SQL 注入),没有为 null
第四个参数:将参数填入前面的语句,用字符串数组传入,和前面的 ?一一对应,没有为 null
*/
db.update(Database.Classes.TABLE_NAME, updates, Database.Classes._ID + " = ?", new String[]{"1"});

参考资料

  1. Android developer: Save data using SQLite
  2. Android developer: SQLiteDatabase
  • Android
  • SQL数据库
Android 保存小技巧
Bellman-Ford:负权值最短路径
© 2024 黑猫
Hexo Theme Yilia by Litten

tag:

  • 图形学
  • 数字图像处理
  • 渲染
  • Unreal
  • Android
  • SQL数据库
  • 架构
  • 旅游
  • Python
  • 算法
  • 线性代数
  • 生活
  • 硬件

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true