Android 数据存储笔记-数据库SQLite
我最近做项目用到了这个sqlite本地数据库,所以写篇博客总结一下,希望也能对小白有所帮助
-
什么时候用sqlite(有固定规则的,大量的数据要保存时)
sharedpreferences是一种轻型的数据存储方式,在保存数据的时候其实存储的是key-value对,类似于map。存储位置:/data/data/应用包名/shared_prefs/文件名.xml。通常用来存储一些简单的配置信息。实际开发中,sharedpreferences共享参数经常存储的数据有app的个性化配置信息、用户使用app的行为信息、临时需要保存的片段信息等。
简单且孤立的数据可保存在sharedpreferences。若是复杂且相互间有关的数据,则要保存在数据库中。(有固定规则的,大量的数据保存在数据库中)
文本形式的数据可保存在sharedpreferences。若是二进制数据,则要保存在文件中。(没有固定规则的,大量的数据保存在文件中)
haredpreferences对象与sqlite数据库相比,免去了创建数据库,创建表,写sql语句等诸多操作,相对而言更加方便,简洁。但是sharedpreferences也有其自身缺陷,比如其只能存储boolean,int,float,long和string五种简单的数据类型,比如其无法进行条件查询等。所以不论sharedpreferences的数据存储操作是如何简单,它也只能是存储方式的一种补充,而无法完全替代如sqlite数据库这样的其他数据存储方式。
sqlite是一个小巧的嵌入式数据库,使用方便、开发简单。它只是一个嵌入式的数据库引擎。在android里,提供了sqlitedatabase类,该类的一个对象就表明一个数据库,其实在底层就是一个文件。默认存储位置:/data/data/<packagename>/databases
-
sqlitedatabase数据库管理类(直接对数据库进行操作)
sqlitedatabase是sqlite的数据库管理类,开发者可以在活动页面代码或任何能取到context的地方获取数据库实例。然后通过sqlitedatabase提供的一些api来对数据库进行操作:
// 创建名叫test.db的数据库。数据库如果不存在就创建它,如果存在就打开它 sqlitedatabase db = openorcreatedatabase(getfilesdir() + "/test.db", context.mode_private, null); // 删除名叫test.db数据库 // deletedatabase(getfilesdir() + "/test.db");
调用该类api要用到sql语句,sqlite的多数sql语法与oracle一样,可以到菜鸟网上查阅:
sqlitedatabase中常用的api:
1. 管理类,用于数据库层面的操作。
- opendatabase:打开指定路径的数据库。
- isopen:判断数据库是否已打开。
- close:关闭数据库。
- getversion:获取数据库的版本号。
- setversion:设置数据库的版本号。
2. 事务类,用于事务层面的操作。
- begintransaction:开始事务。
- settransactionsuccessful:设置事务的成功标志。
- endtransaction:结束事务。执行本方法时,系统会判断是否已执行settransactionsuccessful,如果之前已设置就提交,如果没有设置就回滚。
3. 数据处理类,用于数据表层面的操作。
- execsql:执行拼接好的sql控制语句。一般用于建表、删表、变更表结构。
- delete:删除符合条件的记录。
- update:更新符合条件的记录。
- insert:插入一条记录。
- query:执行查询操作,返回结果集的游标。
- rawquery:执行拼接好的sql查询语句,返回结果集的游标。
但是直接通过sqlitedatabase进行操作数据库非常不方便,必须小心不能重复地打开数据库,处理数据库的升级也很不方便。
因此android提供了一个辅助工具—— sqliteopenhelper,我们可以通过sqliteopenhelper这个数据库帮助器来安全方便地打开、升级数据库。
-
sqliteopenhelper数据库帮助器(安全方便地打开、升级数据库)
使用方法:
新建一个继承自sqliteopenhelper的数据库操作类,提示重写oncreate和onupgrade两个方法。
其中,oncreate方法只在第一次打开数据库时执行,在此可进行表结构创建的操作;
onupgrade方法在数据库版本升高时执行,因此可以在onupgrade函数内部根据新旧版本号进行表结构变更处理。
例如:
//数据库帮助器sqliteopenhelper public class mysqlitehelper extends sqliteopenhelper { public mysqlitehelper(context context, string name, sqlitedatabase.cursorfactory factory, int version) { super(context, name, factory, version); } public mysqlitehelper(context context){ super(context,constant.database_name,null,constant.database_version); } @override public void oncreate(sqlitedatabase db) { // todo 创建数据库后,对数据库的操作
// sql中constant是用来存放一些关于数据库的常量的类
// 类型有:integer、text文本、varchar(n)、real浮点型、blob二进制类型
string sql = "create table if not exists "+constant.table_name+"("+ constant.id+" integer primary key ,"+ constant.user+" text,"+ constant.date+" text,"+ constant.time+" text,"; db.execsql(sql); } @override public void onupgrade(sqlitedatabase db, int oldversion, int newversion) { // todo 更改数据库版本的操作,根据新旧版本号进行表结构变更处理,当打开数据库时传入版本号与当前不同会调用此方法
//在使用中只需要调用构造函数时把版本号参数version改大即可
db.execsql("drop table if exists " + constant.table_name);
oncreate(db);
}
@override
public void onopen(sqlitedatabase db) {
super.onopen(db); // todo 每次成功打开数据库后首先被执行
}
}
-
数据库操作的工具类(封装保证数据库安全的必要方法和操作数据库记录的方法)
在这个类中,封装保证数据库安全的必要方法,包括获取单例对象、打开数据库连接、关闭数据库连接,并且封装对表记录进行增加、删除、修改、查询的操作方法。
获取单例对象:确保app运行时数据库只被打开一次,避免重复打开引起错误。
打开数据库连接:sqlite有锁机制,即读锁和写锁的处理;故而数据库连接也分两种,读连接可调用sqliteopenhelper的getreadabledatabase方法获得,写连接可调用getwritabledatabase获得。
关闭数据库连接:数据库操作完毕后,应当调用sqlitedatabase对象的close方法关闭连接。
例如:
/** * dbmanger 操作我们数据库的工具类 我们一般写成单例模式 * 单例模式 : 在整个应用程序中 不管什么地方(类) 获得的都是同一个对象实例*/ public class dbmanger { private static final string tag = "dbmanger"; private static mysqlitehelper helper; //建立一个数据库对象 //表名 private string table_name ="p_data";
/**单例模式:不能让每一个类都能new一个,那样就不是同一个对象了,所以首先构造函数要私有化,以上下文context作为参数 * @param ctx 本类的上下文对象 * @return */ private dbmanger(context ctx){ //由于数据库只需要调用一次,所以在单例中建出来 helper= new mysqlitehelper(ctx); } //public static 为静态类型,要调用就要有一个静态的变量,为私有的 private static dbmanger instance; //既然该类是私有的 那么别的类就不能够调用 那么就要提供一个public static(公共的 共享的)的方法 //方法名为getinstance 参数为上下文 返回值类型为这个类的实例 //要加上一个synchronized(同步的)如果同时有好多线程 同时去调用getinstance()方法 就可能会出现一些创建多个dbmanger的现象 public static synchronized dbmanger getinstance(context ctx){ //如果为空 就创建一个, 如果不为空就还用原来的 这样整个应用程序中就只能获的一个实例 if(instance == null){ instance = new dbmanger(ctx); } return instance; }//常用方法 增删改查 /** * 添加数据 至数据库 * @param user 用户名 date 日期 time 时间 */ public void adddata(string user,string date,string time){ //获得一个可写的数据库的一个引用 sqlitedatabase db = helper.getwritabledatabase(); contentvalues values= new contentvalues(); values.put(constant.user, user); values.put(constant.date, date); values.put(constant.time, time);// 参数一:表名,参数三,是插入的内容 // 参数二:只要能保存 values中是有内容的,第二个参数可以忽略 db.insert(table_name, null, values); log.d(tag, "adddata: 数据保存成功:"+user+""+date+""+time); } /** * 删除用户 * @param user */ public void deletebyuser(string user){ sqlitedatabase db = helper.getwritabledatabase(); //表名 删除的条件 db.delete(table_name, "user = ?", new string[] {user}); } /** * 删除某条记录 * @param id */ public void deletebyid(int id){ sqlitedatabase db = helper.getwritabledatabase(); //表名 删除的条件 db.delete(table_name, "id = ?", new string[] {integer.valueof(id).tostring()}); } /** * //查找 每一个黑名单都有 号码和模式 先把号码和模式封装一个bean * 获得所有的黑名单 * @param user 用户名 * @param pageindex 页数 * @param pagesize 每页显示的行数 * @return */ //分页查询 修改 p_data是一个新定义的,用来存放一系列数据的类 public list<p_data> getalldata(string user,int pageindex, int pagesize){//创建集合对象 list<p_data> data = new arraylist<p_data>(); sqlitedatabase db = helper.getreadabledatabase();
//cursor cursor = db.query(p_data, null, null, null, null, null, null);//查询全部数据
//order by _id desc 根据_id倒叙排列 使新添加的数据在查询时显示上面。根据用户名查询
//分页查询:pagesize每页显示的数目,pageindex页数 cursor cursor = db.rawquery("select * from p_data where user = ? order by id desc limit "+pagesize +" offset "+((pageindex-1)*pagesize)+";", new string[]{user});
//返回的 cursor 默认是在第一行的上一行 //遍历 while(cursor.movetonext()){// cursor.movetonext() 向下移动一行,如果有内容,返回true string time = cursor.getstring(cursor.getcolumnindex("time")); // 获得time 这列的值 string date = cursor.getstring(cursor.getcolumnindex("date")); // 获得date 这列的值//将查找到的数据封装到bean中 p_data bean = new p_data(user,date,time); //封装的对象添加到集合中 data.add(bean); } //关闭cursor cursor.close(); //systemclock.sleep(1000);// 休眠2秒,查找出的数据比较多、比较耗时的情况下使用 log.d(tag, "getalldata: 查询数据库数据"+data ); return data; } /** * 获得数据的数量 */ public int getnumcount(string user){ sqlitedatabase db = helper.getreadabledatabase(); cursor cursor = db.query(table_name, new string[] {"count(*)"}, "user = ?",new string[] {user}, null, null, null, null); cursor.movetonext(); int count = cursor.getint(0);// 仅查了一列,count(*) 这一刻列 cursor.close(); return count; } }
可被sqlite直接使用的数据结构是contentvalues类,类似于映射map,提供put和get方法用来存取键值对。区别之处在于contentvalues的键只能是字符串”。contentvalues主要用于记录增加和更新操作,即sqlitedatabase的insert和update方法。
对于查询操作来说,使用的是另一个游标类cursor。调用sqlitedatabase的query和rawquery方法时,返回的都是cursor对象,因此获取查询结果要根据游标的指示一条一条遍历结果集合,cursor的常用方法:
1. 游标控制类方法,用于指定游标的状态。
- close:关闭游标。
- isclosed:判断游标是否关闭。
- isfirst:判断游标是否在开头。
- islast:判断游标是否在末尾。
2. 游标移动类方法,把游标移动到指定位置。
- movetofirst:移动游标到开头。
- movetolast:移动游标到末尾。
- movetonext:移动游标到下一条记录。
- movetoprevious:移动游标到上一条记录。
- move:往后移动游标若干条记录。
- movetoposition:移动游标到指定位置的记录。
3. 获取记录类方法,可获取记录的数量、类型以及取值。
- getcount:获取结果记录的数量。
- getint:获取指定字段的整型值。
- getfloat:获取指定字段的浮点数值。
- getstring:获取指定字段的字符串值。
- gettype:获取指定字段的字段类型。
-
在activity、fragment中使用sqlite
创建数据库(oncreateview或oncreate中):
private dbmanger dbmanger;
dbmanger = dbmanger.getinstance(view.getcontext());//fragment dbmanger = dbmanger.getinstance(this);//activity
然后通过dbmanger调用所需的操作函数即可。
-
补充:保存数据的类
public class p_data { private string user; private string date; private string time; public nbp_data( string user, string date, string time) { this.user = user; this.date = date; this.time = time; } public void setdate(string date) { this.date = date; } public void setuser(string user) { this.user = user; } public string getuser() { return user; } public string getdate() { return date; } public string gettime() { return time; } }
-
补充:保存常量的类
public class constant { public static final string database_name = "info.db"; // 数据库名称 public static final int database_version = 1; //数据库版本 public static final string table_name = "p_data"; //数据库表名 /** * id、user、date以下是数据库表中的字段 */ public static final string id = "id"; //id主键 public static final string user = "user"; //用户 public static final string date = "date"; //日期 public static final string time = "time"; //时间 }
上一篇: 小嘴鱼的功效和食用禁忌都有哪些呢?
下一篇: Java实现线程同步方法及原理详解
推荐阅读
-
Android使用文件进行数据存储的方法
-
Android学习笔记--通过Application传递数据代码示例
-
rabbitmq可视化工具数据分析(sqlite数据库可视化工具)
-
python自带数据库好用吗(揭秘SQLite数据库优劣势)
-
python自带数据库好用吗(揭秘SQLite数据库优劣势)
-
Android SQLite数据库增删改查操作的使用详解
-
android中使用SharedPreferences进行数据存储的操作方法
-
Android SQLite数据库增删改查操作的案例分析
-
Android SharedPreferences实现数据存储功能
-
python网络编程学习笔记(九):数据库客户端 DB-API