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# 建表
2create table stu_info (
3 id integer primary key autoincrement,
4 name varchar(30) not null,
5 age integer ,
6 gender varchar(2) not null
7)
8
9# 插入数据
10insert into stu_info(name, age, gender) values ('Mike', 24, '女');
11insert into stu_info(name, age, gender) values ('Jone', 26, '男');
12insert into stu_info(name, age, gender) values ('Tom', 28, '女');
13
14# 查询数据
15select * from stu_info;
16
17# 删除数据
18delete from stu_info where id = 13;
19
20# 修改数据
21update stu_info set name = 'Jack' where id = 10;
22
23# 按条件查询
24select * 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<?xml version="1.0" encoding="utf-8"?>
2<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:tools="http://schemas.android.com/tools"
4 android:layout_width="match_parent"
5 android:layout_height="match_parent"
6 android:orientation="vertical"
7 android:padding="20dp"
8 tools:context=".MainActivity">
9
10 <EditText
11 android:id="@+id/et_name"
12 android:hint="姓名"
13 android:layout_width="match_parent"
14 android:layout_height="wrap_content"/>
15
16 <EditText
17 android:id="@+id/et_age"
18 android:hint="年龄"
19 android:inputType="number"
20 android:layout_width="match_parent"
21 android:layout_height="wrap_content"/>
22
23 <RadioGroup
24 android:id="@+id/rg_sex"
25 android:orientation="horizontal"
26 android:layout_width="match_parent"
27 android:layout_height="wrap_content">
28 <RadioButton
29 android:id="@+id/rb_male"
30 android:text="男"
31 android:layout_width="wrap_content"
32 android:layout_height="wrap_content"/>
33 <RadioButton
34 android:id="@+id/rb_female"
35 android:text="女"
36 android:layout_width="wrap_content"
37 android:layout_height="wrap_content"/>
38 </RadioGroup>
39
40 <LinearLayout
41 android:orientation="horizontal"
42 android:layout_width="match_parent"
43 android:layout_height="wrap_content">
44 <Button
45 android:id="@+id/btn_add"
46 android:text="添加"
47 android:onClick="operatorData"
48 android:layout_width="wrap_content"
49 android:layout_height="wrap_content"/>
50 <Button
51 android:id="@+id/btn_update"
52 android:text="修改"
53 android:onClick="operatorData"
54 android:layout_width="wrap_content"
55 android:layout_height="wrap_content"/>
56 <Button
57 android:id="@+id/btn_delete"
58 android:onClick="operatorData"
59 android:text="删除"
60 android:layout_width="wrap_content"
61 android:layout_height="wrap_content"/>
62 </LinearLayout>
63 <EditText
64 android:id="@+id/et_id"
65 android:hint="修改/删除的ID"
66 android:inputType="number"
67 android:layout_width="match_parent"
68 android:layout_height="wrap_content"/>
69 <ListView
70 android:id="@+id/lv_data"
71 android:layout_width="match_parent"
72 android:layout_height="wrap_content"/>
73</LinearLayout>
MainActivity.java
1public class MainActivity extends AppCompatActivity {
2 private static final String TAG = "MainActivity";
3
4 private EditText etId;
5 private EditText etName;
6 private EditText etAge;
7 private String sex;
8 private SQLiteDatabase sqLiteDatabase;
9 private ListView lvData;
10
11 // 申请权限请求码
12 private static final int REQUEST_EXTERNAL_STORAGE = 1001;
13
14 // 检查权限,这种写法主要是针对比较新的Android6.0及以后的版本
15 public static void verifyStoragePermissions(Activity activity) {
16 int writePermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
17 int readPermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE);
18
19 if (writePermission != PackageManager.PERMISSION_GRANTED
20 || readPermission != PackageManager.PERMISSION_GRANTED) {
21 // 如果没有权限需要动态地去申请权限
22 ActivityCompat.requestPermissions(
23 activity,
24 // 权限数组
25 new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE},
26 // 权限请求码
27 REQUEST_EXTERNAL_STORAGE
28 );
29 }
30 }
31
32 @Override
33 protected void onCreate(Bundle savedInstanceState) {
34 super.onCreate(savedInstanceState);
35 setContentView(R.layout.activity_main);
36 etId = findViewById(R.id.et_id);
37 etName = findViewById(R.id.et_name);
38 etAge = findViewById(R.id.et_age);
39
40 // 单选框组件
41 RadioGroup rgSex = findViewById(R.id.rg_sex);
42 lvData = findViewById(R.id.lv_data);
43 verifyStoragePermissions(this);
44 /*
45 * 构造参数:
46 * 1、上下文
47 * 2、数据库名称,默认位置应用的私有目录(内部存储的database文件夹)
48 * 3、CursorFactory类型
49 * 4、数据库版本
50 */
51 String path = Environment.getExternalStorageDirectory() + "/sqlite_demo.db";
52 SQLiteOpenHelper helper = new SQLiteOpenHelper(this, path, null, 1){
53 // 创建数据库
54 @Override
55 public void onCreate(SQLiteDatabase db) {
56 Toast.makeText(MainActivity.this, "数据库创建", Toast.LENGTH_SHORT).show();
57 // 如果事先没有数据库的话,创建表的操作就可以在这里进行
58 db.execSQL("create table stu_info (id integer primary key autoincrement, name varchar(30) not null, age integer,gender varchar(2) not null)");
59 }
60 // 版本号变化之后会调用这个方法
61 @Override
62 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
63 Toast.makeText(MainActivity.this, "数据库升级", Toast.LENGTH_SHORT).show();
64 }
65 };
66 // 获取数据库对象
67 sqLiteDatabase = helper.getWritableDatabase();
68 // 设置单选框的监听
69 rgSex.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
70 @Override
71 public void onCheckedChanged(RadioGroup group, int checkedId) {
72 switch (checkedId){
73 case R.id.rb_female:
74 sex = "女";
75 break;
76 case R.id.rb_male:
77 sex = "男";
78 break;
79 }
80 }
81 });
82 flushStuData();
83 }
84
85 private void flushStuData() {
86 List<StudentInfo> stuList = new ArrayList<>();
87 String selectSQL = "select * from stu_info";
88 Cursor cursor = sqLiteDatabase.rawQuery(selectSQL, new String[]{});
89 cursor.moveToFirst();
90 while (!cursor.isAfterLast()){
91 int id = cursor.getInt(0);
92 String name = cursor.getString(1);
93 int age = cursor.getInt(2);
94 String sex = cursor.getString(3);
95 stuList.add(new StudentInfo(id, name, age, sex));
96 cursor.moveToNext();
97 }
98 cursor.close();
99 lvData.setAdapter(new StuInfoAdapter(this, stuList));
100 }
101
102
103 public void operatorData(View view) {
104 int viewId = view.getId();
105 switch (viewId) {
106 case R.id.btn_add:
107 if(TextUtils.isEmpty(sex)) {
108 Toast.makeText(MainActivity.this, "请选择性别", Toast.LENGTH_SHORT).show();
109 return;
110 }
111 String insertSQL = String.format(Locale.CHINA,"insert into stu_info(name, age, gender) values ('%s', %d, '%s')",
112 etName.getText().toString(),
113 Integer.parseInt(etAge.getText().toString()),
114 sex);
115 Log.i(TAG, "operatorData: insertSQL = " + insertSQL);
116 sqLiteDatabase.execSQL(insertSQL);
117 // 刷新数据展示
118 flushStuData();
119 Toast.makeText(MainActivity.this, "添加成功", Toast.LENGTH_SHORT).show();
120 break;
121 case R.id.btn_update:
122 String idStr = etId.getText().toString();
123 if(TextUtils.isEmpty(idStr)){
124 Toast.makeText(MainActivity.this, "请输入ID", Toast.LENGTH_SHORT).show();
125 return;
126 }
127 int id = Integer.parseInt(idStr);
128 String updateSQL = String.format(Locale.CHINA,
129 "update stu_info set name = '%s', age=%d, gender='%s' where id = %d",
130 etName.getText().toString(),
131 Integer.parseInt(etAge.getText().toString()),
132 sex, id);
133 Log.i(TAG, "operatorData: updateSQL = " + updateSQL);
134 sqLiteDatabase.execSQL(updateSQL);
135 // 刷新数据展示
136 flushStuData();
137 Toast.makeText(MainActivity.this, "更新成功", Toast.LENGTH_SHORT).show();
138 break;
139 case R.id.btn_delete:
140 String deleteIdStr = etId.getText().toString();
141 if(TextUtils.isEmpty(deleteIdStr)){
142 Toast.makeText(MainActivity.this, "请输入ID", Toast.LENGTH_SHORT).show();
143 return;
144 }
145 String deleteSQL = String.format(Locale.CHINA, "delete from stu_info where id = %d", Integer.parseInt(deleteIdStr));
146 Log.i(TAG, "operatorData: deleteSQL = " + deleteSQL);
147 sqLiteDatabase.execSQL(deleteSQL);
148 // 刷新数据展示
149 flushStuData();
150 Toast.makeText(MainActivity.this, "删除成功", Toast.LENGTH_SHORT).show();
151 break;
152 }
153 }
154}
155
156class StudentInfo {
157 public int id;
158 public String name;
159 public int age;
160 public String sex;
161
162 public StudentInfo() {
163 }
164
165 public StudentInfo(int id, String name, int age, String sex) {
166 this.id = id;
167 this.name = name;
168 this.age = age;
169 this.sex = sex;
170 }
171}
StuInfoAdapter.java
1public class StuInfoAdapter extends BaseAdapter {
2 private List<StudentInfo> stuList;
3 private Activity context;
4
5 public StuInfoAdapter(Activity context, List<StudentInfo> stuList) {
6 this.stuList = stuList;
7 this.context = context;
8 }
9
10 @Override
11 public int getCount() {
12 return stuList.size();
13 }
14
15 @Override
16 public Object getItem(int position) {
17 return stuList.get(position);
18 }
19
20 @Override
21 public long getItemId(int position) {
22 return position;
23 }
24
25 @Override
26 public View getView(int position, View convertView, ViewGroup parent) {
27 ViewHolder viewHolder;
28 if(convertView == null){
29 LayoutInflater inflater = context.getLayoutInflater();
30 convertView = inflater.inflate(R.layout.stu_item, null);
31 viewHolder = new ViewHolder();
32 viewHolder.tvName = convertView.findViewById(R.id.tv_item_name);
33 viewHolder.tvId = convertView.findViewById(R.id.tv_item_id);
34 viewHolder.tvAge = convertView.findViewById(R.id.tv_item_age);
35 viewHolder.tvSex = convertView.findViewById(R.id.tv_item_sex);
36 convertView.setTag(viewHolder);
37 }else {
38 viewHolder = (ViewHolder) convertView.getTag();
39 }
40 StudentInfo studentInfo = stuList.get(position);
41 viewHolder.tvId.setText(String.valueOf(studentInfo.id));
42 viewHolder.tvName.setText(studentInfo.name);
43 viewHolder.tvSex.setText(studentInfo.sex);
44 viewHolder.tvAge.setText(String.valueOf(studentInfo.age));
45 return convertView;
46 }
47
48 // ViewHolder
49 static class ViewHolder{
50 TextView tvId;
51 TextView tvName;
52 TextView tvSex;
53 TextView tvAge;
54 }
55}
最好不要忘记申明读写的权限(以及在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()方法中的使用:
1private void flushStuData() {
2 List<StudentInfo> stuList = new ArrayList<>();
3 // 参数解释:表名、要查询的字段、列条件、列条件参数、GroupBy、having、orderBy
4 Cursor cursor = sqLiteDatabase.query("stu_info", null, null, null, null, null, null);
5 if(cursor.moveToFirst()){
6 do{
7 int id = cursor.getInt(0);
8 String name = cursor.getString(1);
9 int age = cursor.getInt(2);
10 String sex = cursor.getString(3);
11 stuList.add(new StudentInfo(id, name, age, sex));
12 } while (cursor.moveToNext());
13 }
14 cursor.close();
15 lvData.setAdapter(new StuInfoAdapter(this, stuList));
16}
通过API来操作数据库
SQLiteDatabase也提供了insert()、delete()、update()、query()方法专门用于插入、删除、更新和查询,通过这种API的操作方式就需要编写SQL语句了,只需要传入对应的参数,即可完成CRUD操作。还是通过上面的例子,改动的地方无非就是操作数据的部分而已:
1// ...
2
3// 查询
4private void flushStuData() {
5 List<StudentInfo> stuList = new ArrayList<>();
6 // 参数解释:表名、要查询的字段、列条件、列条件参数、GroupBy、having、orderBy
7 Cursor cursor = sqLiteDatabase.query("stu_info", null, null, null, null, null, null);
8 if(cursor.moveToFirst()){
9 do{
10 int id = cursor.getInt(0);
11 String name = cursor.getString(1);
12 int age = cursor.getInt(2);
13 String sex = cursor.getString(3);
14 stuList.add(new StudentInfo(id, name, age, sex));
15 } while (cursor.moveToNext());
16 }
17 cursor.close();
18 lvData.setAdapter(new StuInfoAdapter(this, stuList));
19}
20
21
22public void operatorData(View view) {
23 int viewId = view.getId();
24 switch (viewId) {
25 // 添加
26 case R.id.btn_add:
27 // 参数解释:操作表的名称、可以为空的列、参数
28 ContentValues values = new ContentValues();
29 // Key - value
30 values.put("name", etName.getText().toString());
31 values.put("age", Integer.parseInt(etAge.getText().toString()));
32 values.put("gender", sex);
33 // 插入成功,返回数据的ID
34 long infoId = sqLiteDatabase.insert("stu_info", null, values);
35 // 刷新数据展示
36 flushStuData();
37 Toast.makeText(MainActivity.this, "添加成功,Id = " + infoId, Toast.LENGTH_SHORT).show();
38 break;
39 // 更新
40 case R.id.btn_update:
41 String idStr = etId.getText().toString();
42 ContentValues updateValues = new ContentValues();
43 // Key - value
44 updateValues.put("name", etName.getText().toString());
45 updateValues.put("age", Integer.parseInt(etAge.getText().toString()));
46 updateValues.put("gender", sex);
47 int info = sqLiteDatabase.update("stu_info", updateValues, "id=?", new String[]{idStr});
48 // 刷新数据展示
49 flushStuData();
50 Toast.makeText(MainActivity.this, "更新成功,影响行数:" + info, Toast.LENGTH_SHORT).show();
51 break;
52 // 删除
53 case R.id.btn_delete:
54 String deleteIdStr = etId.getText().toString();
55 int delete = sqLiteDatabase.delete("stu_info", "id=?", new String[]{deleteIdStr});
56 // 刷新数据展示
57 flushStuData();
58 Toast.makeText(MainActivity.this, "删除成功,影响行数:" + delete, Toast.LENGTH_SHORT).show();
59 break;
60 }
61}
62
63// ...
使用LitePal操作SQLite
上面使用SQLiteDatabase来操作SQLite数据库的方法,使用起来真的很不方便,像我这种习惯使用ORM框架的人来说,SQLiteDatabase的操作方式简直太过于复杂,所以现在来看看Litepal这款开源框架吧,使用完过后自己也来尝试造一轮子,可以参考:https://github.com/huyongli/TigerDB
环境搭建
首先引入依赖:
1implementation 'org.litepal.android:core:1.4.1'
接下来需要配置 litepal.xml 文件。右击 app/src/main 目录 —>New—>Directory,创建一个 assets 目录,在assets目录下新建litepal.xml文件:
1<?xml version="1.0" encoding="utf-8" ?>
2<litepal>
3 <!-- 指定数据库名称 -->
4 <dbname value="BookStore"/>
5 <!-- 指定数据库版本号 -->
6 <version value="1"/>
7 <!-- 指定映射模型 -->
8 <list></list>
9</litepal>
最后还需要修改一下 AndroidManifest.xml 中的代码:
1<!-- 关键就这一句:android:name="org.litepal.LitePalApplication" -->
2<application
3 android:name="org.litepal.LitePalApplication"
4 android:allowBackup="true"
5 android:icon="@mipmap/ic_launcher"
6 android:label="@string/app_name"
7 android:roundIcon="@mipmap/ic_launcher_round"
8 android:supportsRtl="true"
9 android:theme="@style/AppTheme">
10 <activity android:name=".MainActivity">
11 <intent-filter>
12 <action android:name="android.intent.action.MAIN" />
13 <category android:name="android.intent.category.LAUNCHER" />
14 </intent-filter>
15 </activity>
16</application>
现在 Litepal 的配置工作已经做完了,让我们开始正式使用它吧!
建库建表
现在开始声明一个JavaBean,也就是我们要存储的数据:
1public class Book {
2 private int id;
3 private String name;
4 private String author;
5
6 public Book(){ }
7
8 public Book(int id, String author, String name) {
9 this.id = id;
10 this.author = author;
11 this.name = name;
12 }
13 // Getter and Setter ...
14}
并且在配置文件中配置它的映射模型:
1<?xml version="1.0" encoding="utf-8" ?>
2<litepal>
3 <!-- 指定数据库名称 -->
4 <dbname value="BookStore"/>
5 <!-- 指定数据库版本号 -->
6 <version value="1"/>
7 <!-- 指定映射模型 -->
8 <list>
9 <mapping class="cn.tim.litepal_demo.Book"/>
10 </list>
11</litepal>
在Activity启动时创建数据库:
虽然有三张表,其中android_matedata表仍然不用管,table_schema表是litepal内部使用的,也可以直接忽视,Book表就是根据配置的Book类自动生成的表,是不是很方便?
数据库升级
而且Litepal很好的解决了数据库升级问题,使用SQLiteOpenHelper来升级数据库的方式:升级数据库的时候我们需要先把之前的表drop掉,然后再重新创建才行。这其实是一个非常严重的问题,因为这样会造成数据丢失,每当升级一次数据库,之前表中的数据就全没了。虽然可以通过复杂的逻辑控制来避免这种情况,但是维护成本很高。而有了LitePal,这些就都不再是问题了,使用LitePal来升级数据库非常非常简单,你完全不用思考任何的逻辑,只需要改你想改的任何内容,然后将版本号加1就行了。
比如,将图书表的中再添加一个价格的字段,再新建一张分类表:
1public class Book {
2 private int id;
3 private String name;
4 private String author;
5 private int price;
6
7 // ...
8}
9
10public class Category {
11 private int id;
12 private String name;
13 private long count;
14
15 // ...
16}
同样需要配置映射模型:
1<?xml version="1.0" encoding="utf-8" ?>
2<litepal>
3 <!-- 指定数据库名称 -->
4 <dbname value="BookStore"/>
5 <!-- 指定数据库版本号:此时数据库版本应该为2 -->
6 <version value="2"/>
7 <!-- 指定映射模型 -->
8 <list>
9 <mapping class="cn.tim.litepal_demo.Book"/>
10 <mapping class="cn.tim.litepal_demo.Category"/>
11 </list>
12</litepal>
由此可见,book表中新增了一个price列,并且新创建了category表。
CRUD操作
下面来看看使用Litepal来对数据进行CRUD是多么方便吧:
首先需要让数据模型对象,也就是定义的Javabean来继承DataSupport
下面直接通过查看log日志的方式来验证LitePal框架的CRUD:
1public class MainActivity extends AppCompatActivity {
2 private static final String TAG = "MainActivity";
3 @Override
4 protected void onCreate(Bundle savedInstanceState) {
5 super.onCreate(savedInstanceState);
6 setContentView(R.layout.activity_main);
7 // 创建数据库
8 SQLiteDatabase database = LitePal.getDatabase();
9
10 // 添加数据
11 Book book = new Book("Think In Java", "Tim", 58);
12 boolean saveRet = book.save();
13 Log.i(TAG, "onCreate: saveRet = " + saveRet);
14 new Book("Think In C/C++", "Tom", 38).save();
15 Log.i(TAG, "onCreate: 添加数据成功");
16
17 // 查询数据
18 List<Book> bookList = DataSupport.findAll(Book.class);
19 Book[] books = new Book[bookList.size()];
20 bookList.toArray(books);
21 Log.i(TAG, "onCreate: books = " + Arrays.toString(books));
22
23 // 删除数据
24 int delete = DataSupport.delete(Book.class, books[0].getId());
25 Log.i(TAG, "onCreate: 删除数据成功,delete = " + delete);
26
27 // 查询数据
28 bookList = DataSupport.findAll(Book.class);
29 books = new Book[bookList.size()];
30 bookList.toArray(books);
31 Log.i(TAG, "onCreate: books = " + Arrays.toString(books));
32
33 // 修改数据
34 Book cppBook = new Book("Think In C/C++", "Tom", 28);
35 int update = cppBook.update(2);
36 Log.i(TAG, "onCreate: 修改数据成功,update = " + update);
37
38 // 查询数据
39 bookList = DataSupport.findAll(Book.class);
40 books = new Book[bookList.size()];
41 bookList.toArray(books);
42 Log.i(TAG, "onCreate: books = " + Arrays.toString(books));
43 }
44}
上面演示了具体的操作,其实还有很多高级查询方法,这里不再赘述,如果用到可以参考作者的博客 《Android数据库高手秘籍》 。