Android开发--Lesson05--SQLite存储数据
概述
SQLite是一种关系型数据库管理系统(RDBMS),它遵循ACID(原子性、一致性、隔离性、持久性)的事务管理原则,特别之处在于它是嵌入式的,并且服务器不需要单独配置和管理。这意味着你可以在无需安装单独数据库服务器软件的情况下使用SQLite,非常适合用于开发桌面应用、移动应用等环境。由于其独特的优势,SQLite在很多场景下都是一个非常不错的选择,比如小型网站、应用程序原型设计、测试环境、教育用途等
SQLite的特点包括:
- 零配置:不需要复杂的安装过程或配置文件,可以轻松地集成到应用程序中。
- 自包含:数据库以单一普通磁盘文件形式保存,易于管理和传输。
- 跨平台支持:可在多种操作系统上运行,包括Windows、Linux、macOS、iOS、Android等。
- 小巧高效:整个库体积小,执行效率高,对资源消耗少,非常适合嵌入式系统和移动设备。
- 公共领域版权:SQLite是在公共领域开放源代码,允许任何人用于任何目的,无需授权费用。
- 支持SQL标准:大部分SQL92标准被支持,使得数据操作更加灵活和强大。
- 事务处理:提供完整的ACID事务支持,确保数据的安全性和完整性。
- 并发访问:通过读写锁机制支持多线程或多进程的并发访问,尽管它不支持高级别的并行写入。
SQLite数据库的理论最大大小是由其页面大小和最大页数决定的。在SQLite中,默认的页面大小是4096字节(可以设置为1024到65536字节之间的任何2的幂),并且数据库的最大页数是31页。基于这些默认值,SQLite数据库文件的理论最大大小大约是:
4096bytes / page x 231 pages = 8TB(字节)
然而,实际上SQLite推荐的最大数据库大小是远低于这个理论极限的,通常建议保持在每个数据库文件1TB以下以保证性能和稳定性。
由于SQLite是内嵌在Android环境中的,所以不需要去额外的安装,需要使用是需要先创建数据库:SQLiteOpenHelper
是 Android 平台提供的一个辅助类,用于简化 SQLite 数据库的创建和管理。它主要负责处理数据库的创建、升级和版本管理等任务。通过使用 SQLiteOpenHelper
,开发者可以避免直接操作底层的 SQLite API,从而更方便地管理数据库。
class MyHelper extends SQLiteOpenHelper{ //构造方法 public MyHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) { //context 上下文 // name 数据库名 // 数据库工厂 //数据版本 super(context, name, factory, version); } //创建数据库相应的表 @Override public void onCreate(SQLiteDatabase db) { //创建一个名为infomation的表,包含id、name、price三个字段 db.execSQL("create table infomation (id integer primary key autoincrement,name varchar(20),price integer)"); } //更新数据库需要用到的方法 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
onCreate(SQLiteDatabase db)
- 当数据库首次创建时调用。
- 在该方法中,开发者通常会执行
CREATE TABLE
等 SQL 语句来初始化数据库表结构
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
-
- 当数据库版本号增加时调用。
- 在该方法中,开发者可以执行必要的数据迁移或表结构调整操作。
构造函数:
context
:应用上下文。name
:数据库文件名。如果为null
,则使用内存数据库。factory
:用于创建游标的工厂类,通常传入null
使用默认实现。version
:数据库版本号,用于管理数据库的升级和降级。
创建数据库表
在SQLite数据库创建数据库表的流程比较简单我们写了一个MyHelper类并且继承SQLiteOpenHelper抽象类,并且实现了写出了两个关键方法,构造方法和onCreate方法,并且onCreate方法中写了在数据库创建的时候创建一张表
故而,我们只需要创建SQLite数据库时就会调用oncretae方法,然后就可以创建数据库表了:
//创建一个MyHelper对象,用于操作数据库 MyHelper myHelper = new MyHelper(MainActivity.this, "data.db", null, 1); //当数据库装满以后,让数据库以只读的方式打开 //获取一个只读的数据库对象 SQLiteDatabase readableDatabase = myHelper.getReadableDatabase(); //关闭数据库连接 readableDatabase.close();
可以通过查询文件的方式判断是否有数据库被创建了,它的位置也在文件存储的位置那里,会新命名一个文件为databases的文件夹,就会装载data.db文件,也是这个数据库的源文件
直接打开这个文件是打不开的,是编码问题,需要使用插件或者第三方APP打开,但是我推荐使用插件的方式打开,比较轻量级
在Android的设置中点击Plugins(插件),搜索 Database Navigator插件
选择安装,然后安装完成之后重启AndroidStudio,然后插件就会被加载在侧边栏,找到SQL Browser,点击它,引入data.db文件所在的位置,这里的db文件需要写你自己的,可以使用Device Explorer来确定文件所在的位置,然后选中
点击SQLite之后,进入连接数据库的页面
然后点击main前面的...,去选中自己的数据库文件所在的位置:
找到自己数据库所在的文件位置之后,点击ok,然后点击右下角的apply,然后点击ok,就可以连接上data.db这个数据库了
然后点击Schemas --> main --> infomation(自己的数据库表名),然后双击它表名,会弹出一个对话框,选中No Filter,即不过滤数据,也就是整表显示所有的数据
不选择过滤器就饿可以将所有的数据都查询出来:
如上图,当我们看到了所有的数据就可以证明,数据库表是创建好了,当然我有数据是因为之前存入的,怎么存储数据,我会在后面的章节说明
SQLite的CRUD
插入操作insert
使用getReadableDatabase获得读取数据库文件的封装对象,使用封装对象可以很快速的CRUD数据,不需要写底层的SQL,是一种高效的开发方式
使用getReadableDatabase获取数据对象需要注意的是,他不是仅仅获得只读对象,而是当数据库存储空间不够时才是只读模式,如果数据库所在的磁盘空间很足够,那么依旧可以写入的也就是默认走的getWritableDatabase对象
//创建一个MyHelper对象,用于操作数据库 MyHelper myHelper = new MyHelper(MainActivity.this, "data.db", null, 1); //当数据库装满以后,让数据库以只读的方式打开 SQLiteDatabase readableDatabase = myHelper.getReadableDatabase(); //创建一个ContentValues对象,用于存储要插入的数据 ContentValues cv = new ContentValues(); //存入数据 cv.put("name","zhangsan"); cv.put("price",Integer.parseInt("18")); //将数据插入到数据库中 long infomation = readableDatabase.insert("infomation", null, cv); //如果插入成功,则弹出提示框 if (infomation>0){ Toast.makeText(MainActivity.this,"插入了"+infomation+"条数据",Toast.LENGTH_LONG).show(); } //关闭数据库连接 readableDatabase.close();
需要对数据进行插入,删除,修改都需要用到ContentValues对象,这是SQLite专门封装的数据操作上下文,使用其它的方式是无法插入的,除非使用的是SQL语句
//创建一个MyHelper对象,用于操作数据库 MyHelper myHelper = new MyHelper(MainActivity.this, "data.db", null, 1); //当数据库装满以后,让数据库以只读的方式打开 SQLiteDatabase readableDatabase = myHelper.getReadableDatabase(); //使用SQL的方式插入数据 readableDatabase.execSQL("insert into infomation(name,price) values('lisi',15)"); //关闭数据库连接 readableDatabase.close();
删除操作delete
MyHelper myHelper = new MyHelper(MainActivity.this, "data.db", null, 1); //当数据库装满以后,让数据库以只读的方式打开 // 获取可读数据库 SQLiteDatabase readableDatabase = myHelper.getReadableDatabase(); // 删除id为1的记录 readableDatabase.delete("infomation","id=?",new String[]{"1"}); // 关闭数据库 readableDatabase.close();
删除操作第一个参数是表名,第二个参数是where语句的条件,第三个参数是?占位符的数据,需要传入String类型,即使在SQLite中是int也传入String类型,在底层会有转换的过程,我们只需要一直保持传入字符串就好
使用SQL的方式删除:
MyHelper myHelper = new MyHelper(MainActivity.this, "data.db", null, 1); //当数据库装满以后,让数据库以只读的方式打开 // 获取可读数据库 SQLiteDatabase readableDatabase = myHelper.getReadableDatabase(); // 删除id为1的记录 readableDatabase.execSQL("delete from infomation where id = 1"); // 关闭数据库 readableDatabase.close();
修改操作update
//创建一个MyHelper对象,用于操作数据库 MyHelper myHelper = new MyHelper(MainActivity.this, "data.db", null, 1); //当数据库装满以后,让数据库以只读的方式打开 SQLiteDatabase readableDatabase = myHelper.getReadableDatabase(); //创建一个ContentValues对象,用于存储要插入的数据 ContentValues cv = new ContentValues(); //将字符串"25"转换为整数,并插入到ContentValues对象中 cv.put("price",Integer.parseInt("25")); //更新数据库中的数据,将name为"ma"的记录的price字段更新为25 int infomation = readableDatabase.update("infomation", cv, "name=?", new String[]{"ma"}); //如果更新成功,则弹出提示框 if (infomation>0){ Toast.makeText(MainActivity.this,"修改了"+infomation+"条数据",Toast.LENGTH_LONG).show(); } //关闭数据库连接 readableDatabase.close();
修改为SQL语句操作
//创建一个MyHelper对象,用于操作数据库 MyHelper myHelper = new MyHelper(MainActivity.this, "data.db", null, 1); //当数据库装满以后,让数据库以只读的方式打开 SQLiteDatabase readableDatabase = myHelper.getReadableDatabase(); //SQL操作修改 readableDatabase.execSQL("update infomation set price = 125 where name = 'ma'"); //关闭数据库连接 readableDatabase.close();
查询操作query
Cursor cursor = readableDatabase.query( "infomation", // 表名 null, // 要查询的列(null 表示查询所有列) "id=?", // WHERE 子句(条件) new String[]{"1"}, // WHERE 子句的参数 null, // GROUP BY 子句 null, // HAVING 子句 null // ORDER BY 子句 );
Cursor
: 返回一个 Cursor
对象。
Cursor
是一个游标,用于遍历查询结果集。- 它类似于一个指针,指向查询到的数据行
- 使用
Cursor
可以逐行读取查询结果。以下是一些常用方法:cursor.moveToFirst()
: 将游标移动到第一行。cursor.getString(columnIndex)
: 获取指定列的字符串值。cursor.getInt(columnIndex)
: 获取指定列的整数值。cursor.moveToNext()
: 将游标移动到下一行。cursor.getCount()
: 获取查询结果的总行数。cursor.close()
: 关闭游标,释放资源。
String id=""; String name=""; String price=""; //创建MyHelper对象,用于操作数据库 MyHelper myHelper = new MyHelper(MainActivity.this, "data.db", null, 1); //当数据库装满以后,让数据库以只读的方式打开 SQLiteDatabase readableDatabase = myHelper.getReadableDatabase(); //查询数据库中id为1的数据 Cursor cursor = readableDatabase.query("infomation", null, "id=?", new String[]{"2"}, null, null, null); //如果查询结果不为空 if (cursor.getCount() != 0){ //遍历查询结果 while (cursor.moveToNext()){ //获取id、name、price字段的值 id = cursor.getString(cursor.getColumnIndex("id")); name = cursor.getString(cursor.getColumnIndex("name")); price = cursor.getString(cursor.getColumnIndex("price")); } } //将查询结果设置到Toast中 Toast.makeText(MainActivity.this,id+","+name+","+price,Toast.LENGTH_LONG).show(); //关闭Cursor cursor.close(); //关闭数据库 readableDatabase.close();
修改为SQL查询,不能使用execSQL,因为没有返回值,需要使用rawQuery方法
String id=""; String name=""; String price=""; //创建MyHelper对象,用于操作数据库 MyHelper myHelper = new MyHelper(MainActivity.this, "data.db", null, 1); //当数据库装满以后,让数据库以只读的方式打开 SQLiteDatabase readableDatabase = myHelper.getReadableDatabase(); //SQL查询 Cursor cursor = readableDatabase.rawQuery("select * from infomation where id = ?", new String[]{"3"}); //如果查询结果不为空 if (cursor.getCount() != 0){ //遍历查询结果 while (cursor.moveToNext()){ //获取id、name、price字段的值 id = cursor.getString(cursor.getColumnIndex("id")); name = cursor.getString(cursor.getColumnIndex("name")); price = cursor.getString(cursor.getColumnIndex("price")); } } //将查询结果设置到Toast中 Toast.makeText(MainActivity.this,id+","+name+","+price,Toast.LENGTH_LONG).show(); //关闭Cursor cursor.close(); //关闭数据库 readableDatabase.close();
------END------