0%

SQLite原理与运用

SQLite是一个开源的关系型数据库,实现自包容、零配置、支持事务的SQL数据库引擎。其特点是高度便携、使用方便、结构紧凑、高效、可靠。并且SQLite是在世界上最广泛部署的 SQL 数据库引擎。SQLite 源代码不受版权限制。 本篇文章书要是记述了SQLite的基本架构以及SQLite的几种操作方式,其中比较重要的就是ADB Shell命令操作与SQL语句,另外在开发中还是Litepal这款开源ORM框架用的比较多一些,使用起来确实非常方便。

SQLite基本结构

接口由SQLite C API组成,程序与SQLite交互的基础就是用C语言编写的API,JDBC也只是JNI调用而已。

在编译器中,词法分析器与语法分析器把SQL翻译为语法树,Code Generator根据语法树生产SQLite的汇编代码,交给虚拟机执行。

虚拟机,与Java虚拟机执行class中的指令类似,SQLite的汇编代码由SQLite虚拟机来执行,由虚拟机负责SQL到数据存取的交互,关于虚拟机的更多内容可以查看官网《The Virtual Database Engine of SQLite》

更多关于SQLite架构的内容可以查看官网《 Architecture of SQLite 》, 里面介绍的比较详细。

SQLite数据类型

类型 类型说明
NULL 这个值为空值
VARCHAR(n) 长度不固定且其最大长度为 n 的字串,n不能超过 4000
CHAR(n) 长度固定为n的字串,n不能超过 254
INTEGER 值被标识为整数,依据值的大小可以依次被存储为1,2,3,4,5,6,7,8
REAL 所有值都是浮动的数值,被存储为8字节的IEEE浮动标记序号
TEXT 值为文本字符串,使用数据库编码存储(TUTF-8, UTF-16BE or UTF-16-LE)
BLOB 值是BLOB数据块,以输入的数据格式进行存储。如何输入就如何存储,不改变格式
DATA 包含了 年份、月份、日期
TIME 包含了 小时、分钟、秒

Android中操作SQLite

SQLite的SQL语句其实和普通SQL没什么特别的不同,Windows下可视化操作SQLite可以使用SQLite Expert Personal 4 - 这款工具,下载地址如下:http://www.sqliteexpert.com/v4/SQLiteExpertPersSetup64.exe。打开后即可通过图形化界面的方式操作SQLite,同样也可以通过SQL语句来操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 建表
create table stu_info (
id integer primary key autoincrement,
name varchar(30) not null,
age integer ,
gender varchar(2) not null
)

# 插入数据
insert into stu_info(name, age, gender) values ('Mike', 24, '女');
insert into stu_info(name, age, gender) values ('Jone', 26, '男');
insert into stu_info(name, age, gender) values ('Tom', 28, '女');

# 查询数据
select * from stu_info;

# 删除数据
delete from stu_info where id = 13;

# 修改数据
update stu_info set name = 'Jack' where id = 10;

# 按条件查询
select * from stu_info where age = 24;

现在主要还是看看在Android平台如何使用吧!SQLiteOpenHelper:Android平台里一个数据库辅助类,用于创建或打开数据库,并且对数据库的创建和版本进行管理。

SQLiteDatabase:用于管理和操作SQLite数据库,几乎所有的数据库操作,最终都将由这个类完成。

ADB Shell操作SQLite

打开CMD窗口,输入adb shell,找到sqlite文件,通过sqlite3 + sqlite文件名就可以进入sqlite shell:

命令 作用
.database 显示数据库信息
.tables 显示表名称
.schema 命令可以查看创建数据表时的SQL命令
.schema table_name 查看创建表table_name时的SQL的命令

SQLiteDatabase + SQL语句

下面这个例子是通过SQLiteDatabase + SQL语句来操作数据库,即需要自己手动拼接SQL,如果是插入数据、修改数据、删除数据都是用sqLiteDatabase.execSQL(insertSQL/updateSQL/deleteSQL)来完成的,查询数据时使用sqLiteDatabase.rawQuery()方法来完成,由于使用起来需要拼接SQL,稍微麻烦一点。

main_activity.xml

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
62
63
64
65
66
67
68
69
70
71
72
73
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="20dp"
tools:context=".MainActivity">

<EditText
android:id="@+id/et_name"
android:hint="姓名"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

<EditText
android:id="@+id/et_age"
android:hint="年龄"
android:inputType="number"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

<RadioGroup
android:id="@+id/rg_sex"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RadioButton
android:id="@+id/rb_male"
android:text="男"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<RadioButton
android:id="@+id/rb_female"
android:text="女"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RadioGroup>

<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn_add"
android:text="添加"
android:onClick="operatorData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/btn_update"
android:text="修改"
android:onClick="operatorData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/btn_delete"
android:onClick="operatorData"
android:text="删除"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<EditText
android:id="@+id/et_id"
android:hint="修改/删除的ID"
android:inputType="number"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ListView
android:id="@+id/lv_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>

MainActivity.java

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";

private EditText etId;
private EditText etName;
private EditText etAge;
private String sex;
private SQLiteDatabase sqLiteDatabase;
private ListView lvData;

// 申请权限请求码
private static final int REQUEST_EXTERNAL_STORAGE = 1001;

// 检查权限,这种写法主要是针对比较新的Android6.0及以后的版本
public static void verifyStoragePermissions(Activity activity) {
int writePermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
int readPermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE);

if (writePermission != PackageManager.PERMISSION_GRANTED
|| readPermission != PackageManager.PERMISSION_GRANTED) {
// 如果没有权限需要动态地去申请权限
ActivityCompat.requestPermissions(
activity,
// 权限数组
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE},
// 权限请求码
REQUEST_EXTERNAL_STORAGE
);
}
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etId = findViewById(R.id.et_id);
etName = findViewById(R.id.et_name);
etAge = findViewById(R.id.et_age);

// 单选框组件
RadioGroup rgSex = findViewById(R.id.rg_sex);
lvData = findViewById(R.id.lv_data);
verifyStoragePermissions(this);
/*
* 构造参数:
* 1、上下文
* 2、数据库名称,默认位置应用的私有目录(内部存储的database文件夹)
* 3、CursorFactory类型
* 4、数据库版本
*/
String path = Environment.getExternalStorageDirectory() + "/sqlite_demo.db";
SQLiteOpenHelper helper = new SQLiteOpenHelper(this, path, null, 1){
// 创建数据库
@Override
public void onCreate(SQLiteDatabase db) {
Toast.makeText(MainActivity.this, "数据库创建", Toast.LENGTH_SHORT).show();
// 如果事先没有数据库的话,创建表的操作就可以在这里进行
db.execSQL("create table stu_info (id integer primary key autoincrement, name varchar(30) not null, age integer,gender varchar(2) not null)");
}
// 版本号变化之后会调用这个方法
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Toast.makeText(MainActivity.this, "数据库升级", Toast.LENGTH_SHORT).show();
}
};
// 获取数据库对象
sqLiteDatabase = helper.getWritableDatabase();
// 设置单选框的监听
rgSex.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId){
case R.id.rb_female:
sex = "女";
break;
case R.id.rb_male:
sex = "男";
break;
}
}
});
flushStuData();
}

private void flushStuData() {
List<StudentInfo> stuList = new ArrayList<>();
String selectSQL = "select * from stu_info";
Cursor cursor = sqLiteDatabase.rawQuery(selectSQL, new String[]{});
cursor.moveToFirst();
while (!cursor.isAfterLast()){
int id = cursor.getInt(0);
String name = cursor.getString(1);
int age = cursor.getInt(2);
String sex = cursor.getString(3);
stuList.add(new StudentInfo(id, name, age, sex));
cursor.moveToNext();
}
cursor.close();
lvData.setAdapter(new StuInfoAdapter(this, stuList));
}


public void operatorData(View view) {
int viewId = view.getId();
switch (viewId) {
case R.id.btn_add:
if(TextUtils.isEmpty(sex)) {
Toast.makeText(MainActivity.this, "请选择性别", Toast.LENGTH_SHORT).show();
return;
}
String insertSQL = String.format(Locale.CHINA,"insert into stu_info(name, age, gender) values ('%s', %d, '%s')",
etName.getText().toString(),
Integer.parseInt(etAge.getText().toString()),
sex);
Log.i(TAG, "operatorData: insertSQL = " + insertSQL);
sqLiteDatabase.execSQL(insertSQL);
// 刷新数据展示
flushStuData();
Toast.makeText(MainActivity.this, "添加成功", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_update:
String idStr = etId.getText().toString();
if(TextUtils.isEmpty(idStr)){
Toast.makeText(MainActivity.this, "请输入ID", Toast.LENGTH_SHORT).show();
return;
}
int id = Integer.parseInt(idStr);
String updateSQL = String.format(Locale.CHINA,
"update stu_info set name = '%s', age=%d, gender='%s' where id = %d",
etName.getText().toString(),
Integer.parseInt(etAge.getText().toString()),
sex, id);
Log.i(TAG, "operatorData: updateSQL = " + updateSQL);
sqLiteDatabase.execSQL(updateSQL);
// 刷新数据展示
flushStuData();
Toast.makeText(MainActivity.this, "更新成功", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_delete:
String deleteIdStr = etId.getText().toString();
if(TextUtils.isEmpty(deleteIdStr)){
Toast.makeText(MainActivity.this, "请输入ID", Toast.LENGTH_SHORT).show();
return;
}
String deleteSQL = String.format(Locale.CHINA, "delete from stu_info where id = %d", Integer.parseInt(deleteIdStr));
Log.i(TAG, "operatorData: deleteSQL = " + deleteSQL);
sqLiteDatabase.execSQL(deleteSQL);
// 刷新数据展示
flushStuData();
Toast.makeText(MainActivity.this, "删除成功", Toast.LENGTH_SHORT).show();
break;
}
}
}

class StudentInfo {
public int id;
public String name;
public int age;
public String sex;

public StudentInfo() {
}

public StudentInfo(int id, String name, int age, String sex) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}
}

StuInfoAdapter.java

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
public class StuInfoAdapter extends BaseAdapter {
private List<StudentInfo> stuList;
private Activity context;

public StuInfoAdapter(Activity context, List<StudentInfo> stuList) {
this.stuList = stuList;
this.context = context;
}

@Override
public int getCount() {
return stuList.size();
}

@Override
public Object getItem(int position) {
return stuList.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView == null){
LayoutInflater inflater = context.getLayoutInflater();
convertView = inflater.inflate(R.layout.stu_item, null);
viewHolder = new ViewHolder();
viewHolder.tvName = convertView.findViewById(R.id.tv_item_name);
viewHolder.tvId = convertView.findViewById(R.id.tv_item_id);
viewHolder.tvAge = convertView.findViewById(R.id.tv_item_age);
viewHolder.tvSex = convertView.findViewById(R.id.tv_item_sex);
convertView.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) convertView.getTag();
}
StudentInfo studentInfo = stuList.get(position);
viewHolder.tvId.setText(String.valueOf(studentInfo.id));
viewHolder.tvName.setText(studentInfo.name);
viewHolder.tvSex.setText(studentInfo.sex);
viewHolder.tvAge.setText(String.valueOf(studentInfo.age));
return convertView;
}

// ViewHolder
static class ViewHolder{
TextView tvId;
TextView tvName;
TextView tvSex;
TextView tvAge;
}
}

最好不要忘记申明读写的权限(以及在Android6.0以后的动态权限申请),最后效果展示如下:

在Android 中使用SQLiteDatabase的静态方法openOrCreateDatabase(String path,SQLiteDatabae.CursorFactory factory)打开或者创建一个数据库。它会自动去检测是否存在这个数据库,如果存在则打开,不存在则创建一个数据库;创建成功则返回一个SQLiteDatabase对象,否则抛出异常FileNotFoundException。

还有需要注意的就是,查询数据返回的结果是Cursor,当我们使用SQLiteDatabase.query()方法时,会得到一个Cursor对象,Cursor指向的就是每一条数据。它提供了很多有关查询的方法,具体方法如下:

方法名称 方法描述
getCount() 获得总的数据项数
isFirst() 判断是否第一条记录
isLast() 判断是否最后一条记录
moveToFirst() 移动到第一条记录
moveToLast() 移动到最后一条记录
move(int offset) 移动到指定记录
moveToNext() 移动到下一条记录
moveToPrevious() 移动到上一条记录
getColumnIndexOrThrow(String columnName) 根据列名称获得列索引
getInt(int columnIndex) 获得指定列索引的int类型值
getString(int columnIndex) 获得指定列缩影的String类型值

这个可以参考在代码示例中flushStuData()方法中的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void flushStuData() {
List<StudentInfo> stuList = new ArrayList<>();
// 参数解释:表名、要查询的字段、列条件、列条件参数、GroupBy、having、orderBy
Cursor cursor = sqLiteDatabase.query("stu_info", null, null, null, null, null, null);
if(cursor.moveToFirst()){
do{
int id = cursor.getInt(0);
String name = cursor.getString(1);
int age = cursor.getInt(2);
String sex = cursor.getString(3);
stuList.add(new StudentInfo(id, name, age, sex));
} while (cursor.moveToNext());
}
cursor.close();
lvData.setAdapter(new StuInfoAdapter(this, stuList));
}

通过API来操作数据库

SQLiteDatabase也提供了insert()、delete()、update()、query()方法专门用于插入、删除、更新和查询,通过这种API的操作方式就需要编写SQL语句了,只需要传入对应的参数,即可完成CRUD操作。还是通过上面的例子,改动的地方无非就是操作数据的部分而已:

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
62
63
// ...

// 查询
private void flushStuData() {
List<StudentInfo> stuList = new ArrayList<>();
// 参数解释:表名、要查询的字段、列条件、列条件参数、GroupBy、having、orderBy
Cursor cursor = sqLiteDatabase.query("stu_info", null, null, null, null, null, null);
if(cursor.moveToFirst()){
do{
int id = cursor.getInt(0);
String name = cursor.getString(1);
int age = cursor.getInt(2);
String sex = cursor.getString(3);
stuList.add(new StudentInfo(id, name, age, sex));
} while (cursor.moveToNext());
}
cursor.close();
lvData.setAdapter(new StuInfoAdapter(this, stuList));
}


public void operatorData(View view) {
int viewId = view.getId();
switch (viewId) {
// 添加
case R.id.btn_add:
// 参数解释:操作表的名称、可以为空的列、参数
ContentValues values = new ContentValues();
// Key - value
values.put("name", etName.getText().toString());
values.put("age", Integer.parseInt(etAge.getText().toString()));
values.put("gender", sex);
// 插入成功,返回数据的ID
long infoId = sqLiteDatabase.insert("stu_info", null, values);
// 刷新数据展示
flushStuData();
Toast.makeText(MainActivity.this, "添加成功,Id = " + infoId, Toast.LENGTH_SHORT).show();
break;
// 更新
case R.id.btn_update:
String idStr = etId.getText().toString();
ContentValues updateValues = new ContentValues();
// Key - value
updateValues.put("name", etName.getText().toString());
updateValues.put("age", Integer.parseInt(etAge.getText().toString()));
updateValues.put("gender", sex);
int info = sqLiteDatabase.update("stu_info", updateValues, "id=?", new String[]{idStr});
// 刷新数据展示
flushStuData();
Toast.makeText(MainActivity.this, "更新成功,影响行数:" + info, Toast.LENGTH_SHORT).show();
break;
// 删除
case R.id.btn_delete:
String deleteIdStr = etId.getText().toString();
int delete = sqLiteDatabase.delete("stu_info", "id=?", new String[]{deleteIdStr});
// 刷新数据展示
flushStuData();
Toast.makeText(MainActivity.this, "删除成功,影响行数:" + delete, Toast.LENGTH_SHORT).show();
break;
}
}

// ...

使用LitePal操作SQLite

上面使用SQLiteDatabase来操作SQLite数据库的方法,使用起来真的很不方便,像我这种习惯使用ORM框架的人来说,SQLiteDatabase的操作方式简直太过于复杂,所以现在来看看Litepal这款开源框架吧,使用完过后自己也来尝试造一轮子,可以参考:https://github.com/huyongli/TigerDB

环境搭建

首先引入依赖:

1
implementation 'org.litepal.android:core:1.4.1'

接下来需要配置 litepal.xml 文件。右击 app/src/main 目录 —>New—>Directory,创建一个 assets 目录,在assets目录下新建litepal.xml文件:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8" ?>
<litepal>
<!-- 指定数据库名称 -->
<dbname value="BookStore"/>
<!-- 指定数据库版本号 -->
<version value="1"/>
<!-- 指定映射模型 -->
<list></list>
</litepal>

最后还需要修改一下 AndroidManifest.xml 中的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- 关键就这一句:android:name="org.litepal.LitePalApplication" -->
<application
android:name="org.litepal.LitePalApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

现在 Litepal 的配置工作已经做完了,让我们开始正式使用它吧!

建库建表

现在开始声明一个JavaBean,也就是我们要存储的数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Book {
private int id;
private String name;
private String author;

public Book(){ }

public Book(int id, String author, String name) {
this.id = id;
this.author = author;
this.name = name;
}
// Getter and Setter ...
}

并且在配置文件中配置它的映射模型:

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="utf-8" ?>
<litepal>
<!-- 指定数据库名称 -->
<dbname value="BookStore"/>
<!-- 指定数据库版本号 -->
<version value="1"/>
<!-- 指定映射模型 -->
<list>
<mapping class="cn.tim.litepal_demo.Book"/>
</list>
</litepal>

在Activity启动时创建数据库:

1
2
// 创建数据库
SQLiteDatabase database = LitePal.getDatabase();

虽然有三张表,其中android_matedata表仍然不用管,table_schema表是litepal内部使用的,也可以直接忽视,Book表就是根据配置的Book类自动生成的表,是不是很方便?

数据库升级

而且Litepal很好的解决了数据库升级问题,使用SQLiteOpenHelper来升级数据库的方式:升级数据库的时候我们需要先把之前的表drop掉,然后再重新创建才行。这其实是一个非常严重的问题,因为这样会造成数据丢失,每当升级一次数据库,之前表中的数据就全没了。虽然可以通过复杂的逻辑控制来避免这种情况,但是维护成本很高。而有了LitePal,这些就都不再是问题了,使用LitePal来升级数据库非常非常简单,你完全不用思考任何的逻辑,只需要改你想改的任何内容,然后将版本号加1就行了。

比如,将图书表的中再添加一个价格的字段,再新建一张分类表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Book {
private int id;
private String name;
private String author;
private int price;

// ...
}

public class Category {
private int id;
private String name;
private long count;

// ...
}

同样需要配置映射模型:

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8" ?>
<litepal>
<!-- 指定数据库名称 -->
<dbname value="BookStore"/>
<!-- 指定数据库版本号:此时数据库版本应该为2 -->
<version value="2"/>
<!-- 指定映射模型 -->
<list>
<mapping class="cn.tim.litepal_demo.Book"/>
<mapping class="cn.tim.litepal_demo.Category"/>
</list>
</litepal>

由此可见,book表中新增了一个price列,并且新创建了category表。

CRUD操作

下面来看看使用Litepal来对数据进行CRUD是多么方便吧:

首先需要让数据模型对象,也就是定义的Javabean来继承DataSupport

1
2
3
public class Book extends DataSupport {
...
}

下面直接通过查看log日志的方式来验证LitePal框架的CRUD:

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
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 创建数据库
SQLiteDatabase database = LitePal.getDatabase();

// 添加数据
Book book = new Book("Think In Java", "Tim", 58);
boolean saveRet = book.save();
Log.i(TAG, "onCreate: saveRet = " + saveRet);
new Book("Think In C/C++", "Tom", 38).save();
Log.i(TAG, "onCreate: 添加数据成功");

// 查询数据
List<Book> bookList = DataSupport.findAll(Book.class);
Book[] books = new Book[bookList.size()];
bookList.toArray(books);
Log.i(TAG, "onCreate: books = " + Arrays.toString(books));

// 删除数据
int delete = DataSupport.delete(Book.class, books[0].getId());
Log.i(TAG, "onCreate: 删除数据成功,delete = " + delete);

// 查询数据
bookList = DataSupport.findAll(Book.class);
books = new Book[bookList.size()];
bookList.toArray(books);
Log.i(TAG, "onCreate: books = " + Arrays.toString(books));

// 修改数据
Book cppBook = new Book("Think In C/C++", "Tom", 28);
int update = cppBook.update(2);
Log.i(TAG, "onCreate: 修改数据成功,update = " + update);

// 查询数据
bookList = DataSupport.findAll(Book.class);
books = new Book[bookList.size()];
bookList.toArray(books);
Log.i(TAG, "onCreate: books = " + Arrays.toString(books));
}
}

上面演示了具体的操作,其实还有很多高级查询方法,这里不再赘述,如果用到可以参考作者的博客《Android数据库高手秘籍》

  • 本文作者: Tim
  • 本文链接: https://zouchanglin.cn/2542596566.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!