Android 应用开发】Android 数据存储 之 SQLite数据库详解(一)

简介: Android 应用开发】Android 数据存储 之 SQLite数据库详解(一)

SQLiteDataBase示例程序下载地址 :


-- GirHub - https://github.com/han1202012/SQLite_NewsList.git.



SQLiteOpenHelper示例程序下载地址 :


-- GitHub : https://github.com/han1202012/NewsSearch.git .




SQLite数据库简介 :


-- 轻量级 : SQLite数据库是一个轻量级的数据库, 适用于少量数据的CURD;


-- 文件本质 : SQLite数据库支持大部分SQL语法, 允许使用SQL语句操作数据库, 其本质是一个文件, 不需要安装启动;


-- 数据读写 : SQLite数据库打开只是打开了一个文件的读写流, 如果有大数据量读写, 需要高并发存储, 那么就不应该使用SQLite;






一. 使用SQLiteDataBase操作数据库



SQLiteDataBase简介 : SQLIteDataBase代表一个数据库, 其本质是一个数据库文件, 创建该类对象, 可以使用该对象的一系列方法操作数据库;




1. SQLiteDataBase方法介绍



(1) 打开数据库方法



使用静态方法打开文件对应的数据库, 数据库文件通常是 文件名.db 形式的;




1> 根据标志位创建数据库



打开数据库: 根据标志位flag要求打开数据库, 这个方法很强大;



public static SQLiteDatabase openDatabase (String path, SQLiteDatabase.CursorFactory factory, int flags)

参数介绍 :

-- 参数① path : path 要打开 或者 需要创建的 数据库文件的路径;


-- 参数② factory : 当打开的数据库执行查询语句的时候 会创建一个Cursor对象, 这时会调用Cursor工厂类 factory, 可以填写null默认值;


-- 参数③ flag :


OPEN_READWRITE 打开一个读写数据库, 如果磁盘满了, 之前写入的也作废;


READ_OPENONLY 打开只读数据库, 这时读取数据库的可靠方法;


CREATE_IF_NECESSARY 打开数据库, 如果数据库不存在, 就创建这个数据库;


NO_LOCALIZED_CALLATORS 打开数据库 不根据本地语言顺序进行排序, 使用这种模式创建数据库, 排序器不会被创建, 使用这个数据库 和 创建这个数据库的时候必须都使用这个标识, 如果这个标识被使用了, 那么setLocal()方法将不会起到任何作用;




2> 根据文件打开或创建数据库



打开数据库 : 根据数据库文件 对象打开数据库, 如果数据库不存在就创建数据库;



public static SQLiteDatabase openOrCreateDatabase (File file, SQLiteDatabase.CursorFactory factory)

相当于   openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY);



3> 根据路径打开或创建数据库



打开数据库 : 根据数据库文件 路径打开数据库, 如果数据库不存在就创建数据库;



public static SQLiteDatabase openOrCreateDatabase (String path, SQLiteDatabase.CursorFactory factory)

相当于   openDatabase(path, factory, CREATE_IF_NECESSARY);




(2) 操作数据库方法



1> 执行SQL语句动态参数



执行SQL语句, 如果需要动态传入SQL语句参数, 将动态参数放入一个Object[]数组中;



public void execSQL (String sql, Object[] bindArgs)

注意 : 该方法 可以 进行增删改操作,  不能进行查询 操作;

该方法适用于 :修改表结构,创建和删除表 触发器 视图 索引等,重建数据库表的索引,数据库升级,事物中保存点,没有返回值的语句;


参数介绍 :


-- 参数① sql: 要执行的SQL语句, 只能执行一条, 多条语句用分号隔开不管用, 参数使用 "?" 占位符代替;


-- 参数② bingArgs: 替换上面SQL语句中的 "?" 占位符, 按照数组中的顺序依次替换;




2> 执行固定的SQL语句



该方法执行固定的SQL语句, 没有参数, 用法与上面的 execSQL(sql, bindArgs)一致;


public void execSQL (String sql)



3> 插入数据



插入数据 : 向数据库中的 一个表 插入 一行 数据;



public long insert (String table, String nullColumnHack, ContentValues values)

参数介绍 :

-- 参数① table : 数据库中的表名, 要插入数据的表;


-- 参数② nullColumnHack : 该参数是可选的, 数据库表中不允许插入一行空的数据, 插入数据至少有一列不为null才能插入, 如果后面的values是null, 并且不知道列的名称, 那么插入操作会失败, 为了避免这种情况, 就出现了本参数, 为了防止 values为null的情况;


-- 参数③ values : 相当于一个Map集合,键 是列名,值 是对应列名要插入的数据;


插入原则 : 不管 第三个 ContentValues参数 是否为null, 执行insert()方法都会添加一条记录, 如果values参数为null, 会添加一个除主键之外其它字段都为null的记录;


nullColumnHack参数作用分析SQL语句 : 在SQL语句中在表名后面必须跟着一个列名, 例如 " insert into appale_info(name) values("乔帮主") ", 这是values参数不为null的情况下,如果values参数为null, 那么导致表名 "apple_info" 后面的列名也为null, 这样SQL语句就不合法了, 因此这里必须加上一个默认的列名, 以防values参数为null;




实例 :



 /

/创建表数据, 键 为 列名, 值 为 对应的表数据
  ContentValues values = new ContentValues();
  values.put("name", "乔帮主");
  values.put("age", 54);
  //向表中插入数据, 如果values为null, 就会添加一个
  long rowsNum = db.insert("apple_info", "name", values);



上面代码转成SQL语句 :


insert into apple_info (name, age) values ('乔帮主', 54)


假如values为null转化成SQL语句 :


insert into apple_info (name) values ()





4> 更新数据



更新指定表中的特定数据 :



public int update (String table, ContentValues values, String whereClause, String[] whereArgs)

参数介绍 :


-- 参数① table : 数据库表名称;


-- 参数② values : 该值类似Map集合, 键 是 列名, 值 是 要更新的数据, 这个值可以为null, 如果为null 这些数据会被清空;


-- 参数③ whereClause: where选择语句, 选择那些行进行数据的更新, 如果该参数为 null, 就会修改所有行;


-- 参数④ whereArgs : where选择语句的参数, 逐个替换 whereClause 中的占位符;


返回值 : 返回修改的行数;


实例 :



//创建表数据, 键 为 列名, 值 为 对应的表数据
  ContentValues values = new ContentValues();
  values.put("name", "乔帮主");
  values.put("age", 54);
  int result = db.update("apple_info", values, "name=?", new String[]{"乔帮主"});
转化为SQL语句: 
update apple_info set name='乔帮主', age=56 where name='乔帮主'



5> 删除数据



删除指定表中特定数据 :



public int delete (String table, String whereClause, String[] whereArgs)

参数介绍 :

-- 参数① table : 要操作的数据库表名;


-- 参数② whereClause : where选择语句, 选择哪些行要被删除, 如果为null, 就删除所有行;


-- 参数③ whereArgs : where语句的参数, 逐个替换where语句中的 "?" 占位符;


实例 :



int result = db.delete("apple_info", "name=?", new String[]{"乔帮主"});
转化为SQL : 
delete apple_info where name='乔帮主'



6> 最全面查询



.



public Cursor query (boolean distinct, String table, String[] columns, 
    String selection, String[] selectionArgs, 
    String groupBy, String having, 
    String orderBy, String limit, 
    CancellationSignal cancellationSignal)

参数介绍 :


-- 参数① distinct : 是否去重复, true 去重复;


-- 参数② table : 要查询的表名;


-- 参数③ columns : 要查询的列名, 如果为null, 就会查询所有的列;


-- 参数④ whereClause : 条件查询子句, 在这里可以使用占位符 "?";


-- 参数⑤ whereArgs : whereClause查询子句中的传入的参数值, 逐个替换 "?" 占位符;


-- 参数⑥ groupBy: 控制分组, 如果为null 将不会分组;


-- 参数⑦ having : 对分组进行过滤;


-- 参数⑧ orderBy : 对记录进行排序;


-- 参数⑨ limite : 用于分页, 如果为null, 就认为不进行分页查询;


-- 参数⑩ cancellationSignal : 进程中取消操作的信号, 如果操作被取消, 当查询命令执行时会抛出 OperationCanceledException 异常;


实例 :



 

Cursor cursor = db.query(true, "apple_info", new String[]{"_id, name, age"},
    "name like ?", new String[]{"乔%"}, 
    null, null, 
    "_id desc", "5, 10");
  cursor.close();



7> 执行SQL查询语句



通过执行SQL语句, 查询结果;



public Cursor rawQuery (String sql, String[] selectionArgs)

参数解析 :

-- 参数① sql : 要执行的SQL语句, 可以使用 "?" 作为占位符;


-- 参数② selectionArgs : sql语句中的参数, 按照次序依次替换占位符 "?";




(3) SQLite中的事务



开启事务 :



public void beginTransaction ()



结束事务 :


public void endTransaction ()



判断当前是否处于事务中 : 如果处于返回true, 反之返回false;


public boolean inTransaction ()



提交事务 : 程序执行endTransaction()方法的时候提交事务 还是 回滚事务, 取决于是否调用了 setTransactionSuccessful()方法, 如果事务执行中调用了改方法, 则提交事务, 如果没有执行该方法, 就会回滚事务;



示例代码 :




         




2. Cursor的相关方法



(1) 移动记录指针方法



1> 移动到指定行数



方法作用 : 将记录指针向上 或者 向下移动offset行, offset为正数就是向下,为负数 就是向上;



public abstract boolean move (int offset)

参数介绍 : offset是移动的相对行数;



2> 移动到第一行



记录指针移动到第一行, 如果移动成功返回true;



public abstract boolean moveToFirst ()




3> 移动到最后一行

记录指针移动到最后一行, 如果移动成功返回true;



public abstract boolean moveToLast ()





4> 移动到上一行



移动到上一行, 成功返回true;



public abstract boolean moveToPrevious ()




5> 移动到下一行



移动到下一行, 成功返回true;



public abstract boolean moveToNext ()




6> 移动到指定行



移动到指定行, 成功返回true;



public abstract boolean moveToPosition (int position)


(2) 获取记录数据方法



获取某个类型的数据 :



public abstract float getFloat (int columnIndex);//获取浮点型数据

public abstract int getInt (int columnIndex);//获取整型数据

public abstract long getLong (int columnIndex);//获取长整型数据

public abstract short getShort (int columnIndex);//获取短整型数据

public abstract String getString (int columnIndex);//获取字符串数据

参数介绍 : 参数是列的标号, 注意该标号从 0 开始计数;




3. sqlite3工具介绍



工具简介 : sqlite3 是一个简单的数据库管理工具, 该用于位于 SDK tools 目录下;




获取数据库文件 : 使用虚拟机运行程序在 data/data/包名 安装目录下, 数据库文件在里面可以找到;




打开数据库 : 进入cmd命令行, 使用sqlite3 数据库文件 命令打开数据库;




常用的sqlite3 工具命令:


-- 打开数据库: sqlite3 文件路径名 ;


-- 查看当前数据库 : .database ;


-- 查看当前数据库中的表 : .tables ;


-- 查看sqlite3的帮助 : .help ;




4. SQLite的数据存储格式



支持的数据类型 : SQLite数据库 内部 只支持null,integer,real(浮点型),text(文本),blob(二进制数据) 五种数据类型;


数据类型转换 : SQLite可以接受varchar(n), char(n), decimal(p,s) 等数据类型, 不过内部的机制使将这个数据类型转换成上面的五种数据类型进行存储;


无类型限制: SQLite允许将各种类型的数据保存到各种类型的字段中, 没有严格的某个字段 必须存放某个类型的数据这样的限制, 因此创建数据库 和 插入数据的时候不用关心这个列的数据类型;


-- eg: 在SQLite中可以将字符串数据放到整型字段中, 但是主键id, 不能随便放其它数据, 只能存放64卫整数;






二. 新闻列表程序实例



1. 要点解析



(1) 数据库相关操作



使用 openOrCreateDatabase()方法创建数据库 : 传入数据库的路径 和 CursorFactory对象;


-- Context.getFilesDir()方法: 该方法返回 内存中应用安装目录中的 文件存储目录的绝对路径, 在这里是 "data/data/shuliang.han.database/files", 整个数据库的完整路径是 :"data/data/shuliang.han.database/files/news.db";



//打开或者创建数据库, 这里是创建数据库
  db = SQLiteDatabase.openOrCreateDatabase(this.getFilesDir().toString() + "/news.db", null);


创建表 :  使用 execSQL()方法 执行SQL语句创建表;

db.execSQL("create table news_table (" +
      "_id integer primary key autoincrement, " +
      "news_tittle varchar(50), " +
      "news_content varchar(5000))");


插入数据 : 调用 execSQL()方法执行插入操作, 传入一个带参数的SQL语句;


db.execSQL("insert into news_table values(null, ?, ?)", new String[]{tittle, content});


查询数据 : 使用 rawQuery()方法, 传入 SQL语句 和 CursorFactory对象, 返回一个Cursor对象;


Cursor cursor = db.rawQuery("select * from news_table", null);


关闭数据库 : 检查 SQLiteDataBase对象 是否为null, 并且 是打开的, 如果符合上面的两个条件, 将db关闭, 这个方法一般是在onDestroy()方法中进行;

@Override
  protected void onDestroy() {
  super.onDestroy();
  //在Activity销毁的时候, 如果没有
  if(db != null && db.isOpen())
    db.close();
  }



(2) ListView相关操作



创建SimpleCursorAdapter适配器 :


参数解析 :


-- 参数① context : 上下文对象;


-- 参数② resource : ListView条目的布局;


-- 参数③ cursor : 从数据库表中查询出来的记录;


-- 参数④ string[]: 数据库中表的字段名称;


-- 参数⑤ int[]: 将数据库中每行的字段 按照对应顺序 放入到该数组对应组件中;



 

SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(
    getApplicationContext(), 
    R.layout.item, 
    cursor, 
    new String[]{"news_tittle", "news_content"}, 
    new int[]{R.id.tittle, R.id.content});



将创建的适配器设置给ListView : 执行这个方法会刷新ListView的显示;


listView.setAdapter(cursorAdapter);


目录
相关文章
|
12天前
|
存储 Java 开发工具
探索安卓应用开发:从新手到专家的旅程
【8月更文挑战第30天】在数字时代,掌握安卓应用开发的技能不仅是职业发展的利器,也是个人技术成长的象征。本文将带你了解如何从零基础开始,逐步深入安卓开发的奥秘,最终成为一名能够独立开发高质量应用的专家。通过实际的代码示例和清晰的步骤指导,我们将一起构建你的第一个安卓应用程序,并探讨如何提升至更高水平。无论你是编程新手还是希望提高现有技能的开发者,这篇文章都将为你提供宝贵的知识和启发。
|
2天前
|
安全 Java Android开发
探索安卓应用开发的新趋势:Kotlin和Jetpack Compose
在安卓应用开发领域,随着技术的不断进步,新的编程语言和框架层出不穷。Kotlin作为一种现代的编程语言,因其简洁性和高效性正逐渐取代Java成为安卓开发的首选语言。同时,Jetpack Compose作为一个新的UI工具包,提供了一种声明式的UI设计方法,使得界面编写更加直观和灵活。本文将深入探讨Kotlin和Jetpack Compose的特点、优势以及如何结合使用它们来构建现代化的安卓应用。
13 4
|
11天前
|
XML Java 开发工具
探索安卓应用开发:从零到一的旅程
【8月更文挑战第31天】跟随一位初学者的视角,本篇文章将带你走进安卓应用开发的奇妙世界。我们将从安装开发工具开始,逐步深入到编写第一个“Hello World”程序,并最终实现一个简单的待办事项应用。通过这个旅程,你将学会如何将创意转化为可触及的应用,体验技术带来的成就感。
|
13天前
|
设计模式 Java Android开发
探索安卓应用开发:从新手到专家的旅程探索iOS开发中的SwiftUI框架
【8月更文挑战第29天】本文旨在通过一个易于理解的旅程比喻,带领读者深入探讨安卓应用开发的各个方面。我们将从基础概念入手,逐步过渡到高级技术,最后讨论如何维护和推广你的应用。无论你是编程新手还是有经验的开发者,这篇文章都将为你提供有价值的见解和实用的代码示例。让我们一起开始这段激动人心的旅程吧!
|
4天前
|
IDE 开发工具 Android开发
探索iOS与安卓应用开发的核心差异
在移动开发的广阔天地中,iOS和安卓这两大平台各领风骚。本文将深入浅出地剖析这两个系统在应用开发上的主要区别,从编程语言到开发环境,再到用户界面设计,我们将一探究竟。无论你是开发者还是对技术充满好奇的读者,这篇文章都将为你打开新世界的大门,带你领略不同平台下的开发魅力。
11 0
|
10天前
|
存储 XML 前端开发
探索Android应用开发:从基础到进阶
【8月更文挑战第31天】在这篇文章中,我们将深入探讨Android应用开发的奥秘。无论你是新手还是有经验的开发者,本文都将为你提供有价值的见解和技巧。我们将从基本的UI设计开始,逐步介绍数据存储、网络请求等高级主题,并展示一些实用的代码示例。让我们一起踏上这段激动人心的旅程吧!
|
10天前
|
缓存 Android开发 UED
安卓应用开发中的性能优化实践
【8月更文挑战第31天】在安卓的世界里,性能是王道。本文将带你深入理解如何通过代码优化和工具使用来提升你的安卓应用性能。我们将一起探索内存管理、布局优化、多线程处理等关键领域,并配以实用的代码示例,让你的应用飞一般地运行起来!
|
10天前
|
XML IDE Java
安卓应用开发入门:打造你的第一个“Hello World”
【8月更文挑战第31天】 在安卓的浩瀚宇宙中,每一个新星都从一句简单的问候开始闪耀。本文将作为你的航标,引导你探索安卓开发的银河系。无论你是初心者还是资深开发者,构建第一个“Hello World”应用总是令人兴奋的里程碑。通过这篇文章,我们将一起搭建起通往安卓开发世界的桥梁。让我们摒弃复杂的术语,用最简单直白的语言,一步步地走过这段旅程。准备好了吗?让我们一起开启这段冒险吧!
|
11天前
|
Java Android开发 开发者
探索安卓应用开发:从基础到实践
【8月更文挑战第31天】在这篇文章中,我们将一起踏上安卓应用开发的旅程。无论你是初学者还是有一定经验的开发者,这里都有适合你的内容。文章将引导你理解安卓开发的基础知识,然后通过实际的代码示例,带你一步步构建一个简单的应用程序。我们的目标是让读者能够不仅理解安卓开发的理论基础,还能通过动手实践来巩固这些知识。所以,拿起你的设备,让我们一起开始吧!
|
11天前
|
移动开发 Java Android开发
探索安卓应用开发的新趋势:Kotlin与Coroutines
【8月更文挑战第31天】本文旨在为读者揭示安卓开发中的最新潮流,特别是Kotlin语言及其协程特性如何重塑移动应用的构建方式。我们将通过实际代码示例深入理解Kotlin简洁语法背后的强大功能,并探讨如何利用Coroutines优雅地处理异步任务,从而提升应用性能和用户体验。无论你是安卓开发的新手还是资深开发者,这篇文章都将为你带来新的启示和灵感。
下一篇
DDNS