前言
- 开始之前,我会new一个project,并add一个empty activity,然后不做其他任何操作。
- 接下来边写文章边敲代码。
- 最终项目在这,非常简单的项目:https://github.com/wodongx123/SQLiteDemo/
1. 定义
SQlite是Android系统内置的一个轻量级的关系型数据库,运行速度快,占用内存小,不仅支持原生的SQL语句还支持ACID事务1,使用甚至不需要账号密码。
2. 创建数据库
-
SQlite的管理需要使用Android提供的SQLiteOpenHelper类,不过这是一个抽象类想要使用它要自己创建一个类来继承它,然后重写其中的方法来消除错误。
public class MyDataBaseHelper extends SQLiteOpenHelper { public myDataBaseHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); } @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { } }
看上去代码很多,其实都是为了消除错误添加的,添加完之后自然而然就长这样了。
其中构造函数有两个方法,我们用参数少的那个,有关构造函数的参数看表。参数 描述 Context 创建数据所需要的环境,一般就传所在的activity name 这个就是数据库的名字了,创建完的数据库的名字就是传入的参数 factory 自定义的游标,没有明确计划或不知道的话就传null version 数据库的版本号,升级版本时用 为了方便,到时候数据库名字就叫BookStore.db。
-
这样一来数据库就算是创建完了,在创建完数据库之后接下来要做的就是建表,表名叫book。
建表的SQL语句:create table book( id integer primary key autoincrement, name text, author text, price integer )
对于SQLite而言,执行sql语句不用太过复杂,直接使用SQLiteDatabase的execSQL()就好,把它写在onCreate()里面。
public class MyDataBaseHelper extends SQLiteOpenHelper { //将建表的SQL语句写成String的常量 public static final String createBookTable = "create table book(\n" + "id integer primary key autoincrement,\n" + "name text,\n" + "author text,\n" + "price integer\n" + ")"; …………………… @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { //执行SQL语句 sqLiteDatabase.execSQL(createBookTable); } …………………… }
-
最后在MainActivity中配置,数据库和表就会自然创建成功。
public class MainActivity extends AppCompatActivity { private MyDataBaseHelper myDataBaseHelper; SQLiteDatabase writableDatabase; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myDataBaseHelper = new MyDataBaseHelper(this, "BookStore.db", null, 1); //获取一个可写的数据库,当管理类发现没有这个数据库的时候,就会新建一个,顺便就执行了oncreate的建表 writableDatabase = myDataBaseHelper.getWritableDatabase(); } }
但是创建完数据库后,要怎么样才能看到内容呢,看不到的话,是不是真的创完数据库和表也很难说吧。这个时候就要使用工具SQLiteStudio了。
- 下载SQLiteStudio,由于是Window和Mac和Linux都能用,不用担心平台问题,链接如果不能用了请自行百度。
https://sqlitestudio.pl/index.rvt?act=download - 在你的Android Studio的右下角有个Device Explorer,点开后找到对应的路径:/data/data/项目名/database/BookStore.db
- 项目名不知道可以打开AndroidManifest.xml查看。
- 把这个BookStore.db右键Save as到一个你知道路径的位置(比如说桌面),然后用SQLiteStudio打开它。
- 可以看到数据库确实有创建,而表也确实存在,就是内部还没有数据。
- 下载SQLiteStudio,由于是Window和Mac和Linux都能用,不用担心平台问题,链接如果不能用了请自行百度。
3. 数据库升级
- 在MyDatabaseHelper类中,还有一个onUpgrade方法是空着没写的,这个方法就是用于升级数据库用,现在的目标是要创建一个新的表People来使用。
可能你会有疑问,为啥两个表不一次性一起创完而是要这样分开创建。实际上在工作中经常会因为更新维护而追加功能,这个people表就是模拟这种追加功能的情况. - 创建People表的SQL:
然后写在onUpgrade()中create table People( id integer primary key autoincrement, name text, age integer )
public class MyDataBaseHelper extends SQLiteOpenHelper { //将建表的SQL语句写成String的常量 public static final String createPeopleTable = "create table People(\n" + "id integer primary key autoincrement,\n" + "name text,\n" + "age integer\n" + ")"; …………………… @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { sqLiteDatabase.execSQL(createPeopleTable); } …………………… }
- 重新运行项目,然后把BookStore.db拉出来查看,发现其中并没有更新People表。这是因为onUpgrade是只有在数据库版本更新的时候才会调用的方法。这个版本,其实就是我们在调用构造函数时所传入的参数。
回到MainActivity,将构造函数的那个版本号1改成2,再次运行项目。 - 再次把BookStore.db保存到本地用SQLiteStudio打开,确认新的表确实有添加。
4. 数据库的CRUD
所谓CRUD,也就是Create,Retrieve,Update,Delete,也就是我们常说的增删改查。在创建完表之后,接下来要做的就是对表内的数据进行增删改查。
4.1 Create
向表内添加新的数据,需要从使用SQLiteDatabase的insert方法。由于在MyDatabaseHelper类不好操作,一般是在外部进行操作,这里就用MainActivity对数据库操作。
public class MainActivity extends AppCompatActivity {
private MyDataBaseHelper myDataBaseHelper;
SQLiteDatabase writableDatabase;
@Override
protected void onCreate(Bundle savedInstanceState) {
……………………
insert();
}
public void insert(){
//获取一个可写的数据库,这样才能写入数据
writableDatabase = myDataBaseHelper.getWritableDatabase();
//对数据库进行增改需要使用ContentValues,它是一个存储类,可以存储大部分基本类型的数据
ContentValues values = new ContentValues();
values.put("name", "hello world");
values.put("author", "aaa");
values.put("price", 100);
//添加数据,
writableDatabase.insert("Book", null, values);
//清空内容,然后写入第二段数据
values.clear();
values.put("name", "hello android");
values.put("price", 200);
//再次添加数据,
writableDatabase.insert("Book", null, values);
}
}
对应的SQL:
insert into Book (name, author, price) values(‘hello world’, ‘aaa’, 100)
insert into Book (name, price) values(‘hello android’, 200)
结果用SQLiteStudio查询。
4.2 Update
添加完数据之后,接下来就是要更新数据了,这个需要使用到update方法。
public class MainActivity extends AppCompatActivity {
private MyDataBaseHelper myDataBaseHelper;
SQLiteDatabase writableDatabase;
@Override
protected void onCreate(Bundle savedInstanceState) {
……………………
//insert();
update();
}
……………………
public void update(){
//获取一个可写的数据库,这样才能更新数据
writableDatabase = myDataBaseHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("author", "bbb");
values.put("price", 150);
writableDatabase.update("Book", values, "name = ?", new String[]{"hello android"});
}
}
有关update方法的参数,第一个第二个参数相当于insert方法的第一个第三个参数,代表表名和数据段,第三个参数则是SQL语句的where部分,而第四个参数则是对第三个参数中的’?‘部分给出具体值,一个数据对应一个问号,而这个’?'就是占位符。不太好理解,但是看完SQL的写法你就懂了。
SQL:
update Book set author = ‘bbb’, price = 150 where name = ‘hello android’
4.3 Delete
不用多描述了,看看怎么写的就好,调用Delete方法。
public class MainActivity extends AppCompatActivity {
private MyDataBaseHelper myDataBaseHelper;
SQLiteDatabase writableDatabase;
@Override
protected void onCreate(Bundle savedInstanceState) {
……………………
// insert();
// update();
delete();
}
……………………
public void delete(){
writableDatabase = myDataBaseHelper.getWritableDatabase();
writableDatabase.delete("Book", "author = ?", new String[]{"bbb"});
}
}
SQL:
delete from Book where author = ‘bbb’
4.4 Query
对于数据库最重要的内容而言,就是查询。查询功能非常重要,所以就算是最直接的query方法也带有非常多参数,在此我先对参数进行描述说明。
参数 | 对应SQL部分 | 备注 |
---|---|---|
table | from table_1 | 查询某个应用中的某个表 |
column | select column1, column2 | 查询指定的列名,如果为空就是选择所有列(相当于*) |
selection | where column = value | 约束条件,如果为空就是没有约束条件 |
selectionArgs | - | 为where中的占位符提供具体的值,为空就是无具体值,为new String[]{}形式 |
groupBy | group by column | 指定需要group by的列,可为空 |
having | having column = value | 对group by后的列进一步约束,可为空 |
orderBy | order by column1 | 指定查询结果的排列方式,可为空 |
这里为了方便,大部分参数到时候就都为空了。
public class MainActivity extends AppCompatActivity {
private MyDataBaseHelper myDataBaseHelper;
SQLiteDatabase writableDatabase;
SQLiteDatabase readableDatabase;
@Override
protected void onCreate(Bundle savedInstanceState) {
……………………
//为了让结果数据多一点,就再插入两条数据
insert();
// update();
// delete();
query();
}
……………………
public void query(){
//由于不用对数据做改动,所以只要获取只读的数据库即可
readableDatabase = myDataBaseHelper.getReadableDatabase();
//查询语句,要注意返回的是一个Cursor对象
Cursor cursor = readableDatabase.query("Book", null, null, null, null, null, null);
//如果查询的数据为空就返回
if (!cursor.moveToFirst())
return;
//当游标没到末尾时就一直遍历内部的数据
do{
String name = cursor.getString(cursor.getColumnIndex("name"));
int price = cursor.getInt(cursor.getColumnIndex("price"));
//为了方便,获得的数据就用log打出
Log.i("MainActivity", "query: " + name + " " + price);
}while(cursor.moveToNext());
//用完之后要记得关掉
cursor.close();
}
}
SQL:
select * from Book
参考材料
第一行代码——Android(第2版)
p211 - p229
有关ACID这个看百科就好了:
https://baike.baidu.com/item/ACID/10738 ↩︎