听说点赞关注的人,身体健康,万事如意,工作顺利,爱情甜蜜,一夜暴富,升职加薪……最终迎娶白富美!!!
‼️微信公众号:炜煜工作室
🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱
📡 :安卓开发基础知识-补习5💯
📰内容简介:
本文通过…….介绍了……通过……实现了……使用java代码进行开发,如果有问题的地方请不吝指教,如果对文内内容有不理解的地方,也希望能积极主动的联系博主进行深刻的探讨,以便于让博主更深刻的记住这篇博文的内容,好让博主在发光发热的道路上越走越远。[手动狗头]🐶努力,奋斗!
📎 标签:安卓;java;SQLite;C;基本操作;
🔍一、SQLite数据库
上篇简单介绍了SQLite数据库,这篇主要讲解SQLite的创建和使用。
-
安卓系统中提供了相关的类帮助我们创建数据库,其中,SQLiteOpenHelper是安卓提供的管理数据的工具类。主要用于数据库的创建,打开和版本更新,一般用法是创建SQLiteOpenHelper类的子类,并重写父类的onCreate()方法和onUpgrade()方法(这两个方法是抽象的必须重写)。
-
抽象方法(抽象类):抽象方法充当着占位方法的角色,他们在子类中具体实现。扩展抽象类可以有两种选择。一种实在子类种保留抽象类中的部分或所有抽象方法任未定义,这样就必须将子类也标记未抽象类。另一种做法是定义全部方法,这样一来,子类就不是抽象的了。
- 即使不包含抽象防范,也可以将类申明为抽象类。
- 抽象类不能实例化。也就是不能创建这个类的对象。
- 不能new对象,但是可以创建一个类的子类。可以定义一个抽象类的对象变量,但是这样一个变量只能引用非抽象子类的对象。
-
SQLiteOpenHelper包含如下常用的方法
-
abstract void onCreate(SQLiteData db); //当数据库第一次被常见的时候调用该方法。 abstract void onUpgrade(SQLiteDatabase db); //当数据库需要更新的时候调用该方法。 SQLiteDatabase getWriteableDatabase(); //以写的方式打开数据库对应的SQLiteDatabase对象,一旦打开成功,将会缓存该数据库对象。 SQLiteDatabase getReadableDatabase(); //以读写的方式打开数据库对应的SQLiteDatabase对象,该方法内部调用getWriteableDatabase()方法,返回对象与getWriteableDatabase()返回对象一致,除非数据库的磁盘空间满了,此时getWriteDatabase()打开数据库就会出错,当打开失败后getReadableDatabase()方法会继续尝试以制度方式打开数据库。 //当调用SQLiteOpenHelper的gerWriteOpenHelper的getWriteableDatabase()或者getReadableDatabase()方法获取SQLiteDatabase实例的是偶,如果数据库不存在,安卓系统会自动生成一个方法在数据库库版本号发生变化时会被调用,一般软件升级需要修改表结构的时候需要升级数据库版本号,假设数据库原有版本时是1,当要修改表结构时就需要升级版本号,此时可以设置数据库版本号2,饼子并在onUpgrade()方法中实现表结构的更新。onUpgrade()方法在数据库版本号发生变化时会被调用,并做出相应表结构和数据的更新,如果版本号不增加,则该方法不会被调用。
import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import androidx.annotation.Nullable; public class SQLiteDemo extends SQLiteOpenHelper { public SQLiteDemo(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) { super(context, "userInfo.db", null, 1); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table if not exists " + " userInfo " + "(" + "_id integer primary key " + "autoincrement," + "user_name varchar," + "user_pwd varchar," + "user_nick varchar" + ")"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
上述代码中,首先创建另一个SQLiteHelper类继承自SQLiteOpenHelper,并重写该类的构造方法SQLiteHelper(),在该方法中通过super()调用父类SQLiteOpenHelper的构造方法,并传入4个参数,分别表示上下文对象,数据库名称,游标工厂(通常是null)、数据库版本。然后重写了onCreate()和onUpgrade()方法,其中,onCreate()方法是在数据库第一次创建时调用,该方法通常用于初始化表结构。MainActivity.java中的代码。
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); SQLiteDemo sqLiteDemo = new SQLiteDemo(this,"userInfo",null,1); SQLiteDatabase database = sqLiteDemo.getWritableDatabase(); } }
上述代码首先生成SQLiteDemo对象,调用该方法的getWriteableDatabase()生成数据库,程序运行后,在Device File Explorer视图中找到数据库文件所在的路径data/data/com.example.administrator.chart0705/database/userInfo.db
-
SQLite数据库的升级
创建好数据库之后,如果需要需要在数据库中添加表就可以在onCreate中添加如下语句:
public void onCreate(SQLiteDatabase db){
db.execSQL("create table if not exists"+"表名"+字段名 类型,,,,)
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists userInfo");
onCreate(db);
}
SQLite数据库的基本操作
1. SQLite数据库的特点:
- SQLite是一款轻量级的嵌入式数据库(用于移动端)
- 处理数据的速度, 比MySQL还要快
- SQLite不需要进行配置(只需要引入依赖库, 和头文件),这就意味着不需要安装
- SQLite的一个不需要单独服务器进行(维护)操作的系统, 是完全自己独立
- SQLite是非常小的, 完全配置时小于400K, 当省略一些可选文件时小于250K
- SQLite是自给自足的, 也就意味着不需要任何的外部依赖
2. SQLite数据库的基本操作
打开数据库格式 : sqlite3_open(数据库路径.UTF8String, 指向数据库的地址的地址);
创建表格式: create table 表名 ( 字段名1 字段类型 约束1 约束2 ,字段2 约束2);
插入数据(增)格式: insert into 表名(name,age) values(‘大王',10);
删除数据(删)格式: delete from 表名 where 条件
修改数据(改)格式: update 表名 set 字段名 = 值 where 条件字段 = 满足条件//修改的不仅仅是一条记录
查询数据(查)格式: select 字段* from 表名 where 条件
关闭数据库格式: sqlite3_close(数据库指针);
3. SQLite的具体实例应用
文件结构
- 单例类(DataBaseHandle)(工具类, 所有sqlite语句都封装到该类中, 在controller中用该类的对象调用数据库的基本操作(方法))
- controller类(ViewConteoller)(类中调用单例类, 并初始化一个单例类对象, 调用数据库操作方法)
文件内容
DataBaseHandle.h文件
#import <Foundation/Foundation.h>
//第一步: 导入依赖库
//第二步: 引入头文件
#import <sqlite3.h>
@interface DBHandle : NSObject
//初始化单例类对象的方法
+ (DBHandle*)shareDBHandle;
//打开数据库方法
- (void)openDB;
//关闭数据库方法
- (void)closeDB;
//建表
- (void)setCreate;
//增加记录(此处以姓名,年龄)
- (void)insertWithName:(NSString *)name age:(NSInteger)age;
//删除记录(SID)
- (void)deleteStudentByID:(NSInteger)SID;
//更新数据(根据字段age)
- (void)updateWithAge:(NSInteger)age;
//查找数据(根据字典name)
- (void)selectWithName:(NSString *)name;
//删除表
- (void)clearDB;
@end
DataBaseHandle.m文件
#import “DBHandle.h”
//创建代理对象
static DBHandle *dataBase = nil;
@interface DBHandle ()
//保存数据库路径
@property (nonatomic, copy)NSString *dataBasePath;
@end
@implementation DBHandle
实现数据库操作的方法
//初始化单例类对象的房
+ (DBHandle *)shareDBHandle{
if (dataBase == nil) {
dataBase = [[DBHandle alloc] init];
}
return dataBase;
}
*返回数据库文件路径
- (NSString *)dataBasePath{
if (_dataBasePath == nil) {
//1. 获取数据库路径
NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)firstObject];
//2. 拼接数据库文件
_dataBasePath = [documents stringByAppendingString:@"/student.sqlite"];
}
return _dataBasePath;
}
*数据库指针
//数据库指针: 因为好多地方都会使用到数据库, 所以初始化一个数据库静态变量
//创建数据库指针
static sqlite3 *db = nil;
*打开数据库方法
//打开数据库方法
- (void)openDB{
NSLog(@"databasePath = %@", self.dataBasePath);
//定义一个BooL类型的数据, 用来接收打开数据库的结果
//参数一: 数据库存储的路径 (c语言形式.UTF8String)
//参数二: 数据库的地址 &
BOOL result = sqlite3_open(self.dataBasePath.UTF8String, &db);
if (result == SQLITE_OK) {
NSLog(@"打开成功");
}else{
NSLog(@"打开失败");
}
}
* 关闭数据库方法
//关闭数据库方法
- (void)closeDB{
BOOL result = sqlite3_close(db);
if (result == SQLITE_OK) {
NSLog(@"关闭成功");
}else{
NSLog(@"关闭失败");
}
}
*建表
//建表
- (void)setCreate{
//1. 准备SQL语句 , 创建一个Stu表
NSString *sqlString = @"create table if not exists stu(s_id integer primary key autoincrement not null, s_name text, s_age integer)";
//2. 执行SQL语句
//参数一: 数据库
//参数二: 要执行的sql语句(要求转换成C语言的格式)
//参数三: 表示结果回调一个函数
//参数四: 回调一个函数参数
//参数五: 错误信息
int result = sqlite3_exec(db, sqlString.UTF8String, NULL, NULL, NULL);
if (result == SQLITE_OK) {
NSLog(@"创建表成功");
}else{
NSLog(@"创建表失败%d", result);
}
}
* 增加记录(此处以姓名,年龄)
//增加记录(此处以姓名,年龄)
- (void)insertWithName:(NSString *)name age:(NSInteger)age{
//1. 准备SQL语句(当values的值不确定的时候,需要使用"?"来代替, 之后需要对其进行绑定)
NSString *SQLString = @"insert into stu(s_name, s_age) values(?,?)";
//2. 创建伴随指针(用于绑定参数, 获取数据)
sqlite3_stmt *stmt = NULL;
//3. 预执行
//参数一: 数据库
//参数二: sql语句(C语言的格式, 所以需要进行转码:UTF8String)
//参数三: 有正负之分(正: 代表只往后读一个字节. 负: 遇到特殊符号才会结束,例如:\000, u000) s_name = @"zhang\000san"
//参数四: 伴随指针的地址
//参数五: 表示取值的时候只取一部分, 剩余的部分会存储在这里
int result = sqlite3_prepare(db, SQLString.UTF8String, -1, &stmt, NULL);
if (result == SQLITE_OK) {
NSLog(@"添加预处理成功");
//4. 绑定参数
//参数一: 伴随指针 -->用于绑定参数,获取数值
//参数二: 绑定参数位置( "?" 的位置, 从1开始)
//参数三: 表示要插入的值(形参),需要进行UTF8String转换
//参数四: 有正负之分(正: 代表只往后读一个字节. 负: 遇到特殊符号才会结束,例如:\000, u000) s_name = @"zhang\000san"
//参数五: 回调一个函数
sqlite3_bind_text(stmt, 1, name.UTF8String, -1, NULL); //对Name进行绑定
sqlite3_bind_int64(stmt, 2, age);
//5. 执行伴随指针(sql语句执行完毕后, 根据伴随指针的情况判断是否插入成功(SQLITE_DONE: 表示伴随指针执行数据成功))
if (sqlite3_step(stmt) == SQLITE_DONE) {
NSLog(@"插入成功");
}else{
NSLog(@"插入失败%d", result);
}
}else{
NSLog(@"添加预处理失败%d", result);
}
//6. 释放伴随指针
sqlite3_finalize(stmt);
//第二种方式:
//NSString *SQLString = [NSString stringWithFormat:@"insert into stu(s_name, s_age) values('%@', %ld)",name, age];
//int result = sqlite3_exec(db, SQLString.UTF8String, NULL, NULL, NULL);
}
* 删除记录(SID)
//删除记录(SID)
- (void)deleteStudentByID:(NSInteger)SID{
//1. 准备SQL语句
NSString *sqlString = [NSString stringWithFormat:@"delete from stu where s_id = %ld",SID];
//2. 执行sql语句
int result = sqlite3_exec(db, sqlString.UTF8String, NULL, NULL, NULL);
//3. 结果
if (result == SQLITE_OK) {
NSLog(@"删除数据成功%ld", SID);
}else{
NSLog(@"删除失败%d", result);
}
}
*更新数据(根据字段age)
//更新数据(根据字段age)
- (void)updateWithAge:(NSInteger)age{
//1. 准备SQL语句(无条件时, 不做更新)
NSString *sqlString = @"update stu set s_age = ? where s_age = 18";
//2. 创建伴随指针
sqlite3_stmt *stmt = NULL;
//3. 预执行
int result = sqlite3_prepare(db, sqlString.UTF8String, -1, &stmt, NULL);
if (result == SQLITE_OK) {
NSLog(@"预处理成功");
//4. 绑定参数
sqlite3_bind_int64(stmt, 1, age);
//5. 执行判断伴随指针是否绑定成功
if (sqlite3_step(stmt) == SQLITE_DONE) {
NSLog(@"更新成功");
}else{
NSLog(@"更新失败");
}
}else{
NSLog(@"语句错误");
}
//6. 释放伴随指针
sqlite3_finalize(stmt);
//第二种方法:
//NSString *sqlString = [NSString stringWithFormat:@"update stu set s_age = %ld where s_age = 20", age];
//int result = sqlite3_exec(db, sqlString.UTF8String, NULL, NULL, NULL);
}
*查找数据(根据字典name)
//查找数据(根据字典name)
- (void)selectWithName:(NSString *)name{
//1. 准备sql语句
//NSString *sqlString = @"select * from stu where s_name = ?";
NSString *sqlString = [NSString stringWithFormat:@"select * from stu where s_name = '%@'", name]; //添加 单引号
//2. 创建伴随指针
sqlite3_stmt *stmt = nil;
//3. 预执行
int result = sqlite3_prepare(db, sqlString.UTF8String, -1, &stmt, NULL);
if (result == SQLITE_OK) {
//4. 绑定数据
sqlite3_bind_text(stmt, 1, name.UTF8String, -1, NULL);
while (sqlite3_step(stmt) == SQLITE_ROW) {
//从伴随指针获取数据(第一列)
int s_id = sqlite3_column_int(stmt, 0);
//从伴随指针获取数据(第二列)
NSString *s_name = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(stmt, 1)];
//从伴随指针获取数据(第三列)
int s_age = sqlite3_column_int(stmt, 2);
NSLog(@"s_id = %d, s_name = %@, s_age = %d", s_id, s_name, s_age);
}
}else{
NSLog(@"查找失败%d", result);
}
//释放伴随指针
sqlite3_finalize(stmt);
}
* 清除表内容 和删除数据库表
//清除表内容 和删除数据库表
- (void)clearDB{
//1. 准备sql 语句
NSString *sql = @"delete from stu";
//删除表
//NSString *sql = @"drop table stu";
//2. 执行
sqlite3_exec(db, sql.UTF8String, NULL, NULL, NULL);
}
@end
viewController.m文件
#import "DBHandle.h"
DBHandle *db = [DBHandle shareDBHandle];
//打开数据库
[db openDB];
//建表
[db setCreate];
//插入
[db insertWithName:@"帅哥" age:20];
//删除
//[db deleteStudentByID:1];
//更新
[db updateWithAge:10];
[db selectWithName:@"美女007"];
[db clearDB];
//关闭数据库
[db closeDB];
上述代码通过C语言处理,所使用的步骤和语句类似java,后续具体使用的时候再按照兵及逆行查询。
-
增加数据
public void insert(String name ,String pwd,String nick){ SQLiteHelper sqLiteHelper = new SQLiteHelper(this); SQLiteDatabase database = sqLiteHelper.getWriteableDatabase(); ContentValues values = new ContentValues(); values.put("user_name",name); values.put("user_pwd",pwd); values.put("user_nick",nick); long id = database.insert("userinfo",null,values); database.close(); }
先通过sqliteHelper的getWriteDatabase获取sqliteDatabase对象,之后获取ContentVlues对象并将数据提娜佳到ontentVlues对象中。最后调用inset()方法将数据添加到userInfo表中,返回值代表新行的ID。其中insert()方法接受3个参数,第一个参数是表名。第二个参数表示如果发现将要插入的行为空行时,会将这个列的值设置为null,第3个参数为ContentValues对象。其中,ContentValues类类似Map类,通过键-值对的形式存入数据,这里的key表示插入数据的列民。value表示要插入的数据。
需要注意的时,使用完SQLiteDatabase对象后,一定要调用close()福安比数据库连接,否则数据库连接会一致存在,不断消耗内存,当系统内存不足时将获取不到SQLiteDatabase对象,并且会爆出数据库未关闭的异常。
-
修改数据
public int update(String name ,String pwd,String nick){ SQLiteHelper helper = new SQLiteHelper(this); SQLiteDatabase database = sqLiteHelper.getWriteableDatabase(); ContentValues values = new ContentValues(); values.put("user_pwd",pwd); values.put("user_nick",nick); int num = database.update("userinfo",values,"user_name=?",new String[]{name}); database.close(); return num; }
上述代码中,首先通过SQLitehelper的getWriteableDatabase()方法回去sqiteDatabase对象,之后调用该方法的update()方法,其中updata方法接受3个参数。第一个参数时表名,第2个参数表示查询条件的自居,第三个参数为查询条件自居中对应的值。该方法返回值表示受影响的行数。
-
删除数据
public int delete(String name){ SQLiteHelper sqLiteHelper = new SQLiteHelper(this); SQLiteDatabase database = sqLiteHelper.getWriteableDatabase(); int num = database.delete("userinfo","user_name=?",new String[]{name}); database.close(); return num; }
上述代码通过sqliteHelper的getWriteDatabase获取SQLiteDatabase对象,之后调用该对象的delete()方法,其中给,delete()方法接受3个参数,第一个参数是表名,第二个参数表示查询条件的子句,第三个参数为查询条件子句中对应的值。该方法的返回值表示受影响的行数。
-
查询数据
进行数据查询的时候使用的是query()方法啊,该方法返回的是一个行数集合Cursor,Cursor是一个游标接口,提供了遍历查询结果的方法,需要注意的是,在使用完Cursor对象后,一定更要及时关闭,否则会造成内存泄露。以userInfo表为例
public List<UserInfo> query(String name){ List<UserInfo> infoLise = new SQLiteHelper(this); SQLiteDatabse database = sqliteHelper.getWriteableDatabase(); Cursor cursor = database.query("userinfo",null,"user_name=?",new String[]{name}null,null,null,null); if(cursor != null && cursor.gerCount() > 0){ while(cursor.moveToNext()){ UserInfo info = new UserInfo(); info.setUser_name(cursor.getString(1)); info.setUser_pwd(cursor.getString(2)); info.setUser_nick(cursor.getSting(3)); infoList.add(info); } } cursor.close(); database.close(); return infoLst(); }
上述代码中,封装一个查询表userInfo的方法,其中返回为一个集合,结合中每个对象的类型为UserInfo。UserInfo是更具userInfo表封装的实体类。
其中,第1·6行代码首先通过sqliteHelper的getWriteableDatabase()获取seliteDatabase对象,再通过SQLiteDatabase对象的query()方法查询ueriInfo表中的数据,并返回Cursor对象。query方法包含7个参数,
- 1,名称
- 2,指明查询哪几列
- 3,接受查询条件的子句
- 4,接受查询子句对应的条件值
- 5,表示分组
- 6,接受having条件,即对group by之后哦的数据再添加过滤器
- 7,表示排序方式。如果不指明,则按照默认的排序方式。
🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱
📌内容总结:
🕥本文通过……介绍了……还有🐛没有写到本文内,后续内容可以继续追踪博主的后续文章,或许会介绍相关的内容,如果没介绍,请用力踢一脚,好让摸鱼的博主积极主动的去认识错误并及时改正,在发光发热的道路上越走越远……
表情网站:[🎁 Emoji cheat sheet for GitHub, Basecamp, Slack & more (webfx.com)