持久化存储---Sqlite的初步认识

作者: pgydbh | 来源:发表于2018-05-01 23:24 被阅读38次
    引用了大部分:https://www.cnblogs.com/foxy/p/7725010.html

    目录

    无标题.png

    问题&解惑

    问题1:为什么要用到sqlite这种本地数据库
    答案:结构化的大量数据存储的最好方式就是数据库形式,而现在的app为了给用户好的体验(主要是离线模式),经常会需要本地存储一些数据,供用户使用。
    问题2:sqlite的优点
    答案:轻量级,使用SQLite一般只需要带上它的一个动态库,只有几百kb,且不用安装,开源。
    问题3:用到数据库的例子
    答案:聊天记录,新闻类未联网进去后依旧还是有内容item显示,Android系统内联系人应该也是用数据库存储。

    Sqlite数据类型

    以下来自网络
    varchar 可以提供默认值,text 没有
    varchar 会有自己设置的上限,优点:可以防止一些错误大数据, 缺点:字符串会被截断
    text可变,默认最大上限为 65535
    类型 含义
    NULL 这个值为空值
    VARCHAR(n) 长度不固定且其最大长度为 n 的字串,n不能超过 4000。
    CHAR(n) 长度固定为n的字串,n不能超过 254。
    INTEGER 值被标识为整数,依据值的大小可以依次被存储为1,2,3,4,5,6,7,8.
    REAL 所有值都是浮动的数值,被存储为8字节的IEEE浮动标记序号.
    TEXT 值为文本字符串,使用数据库编码存储(TUTF-8, UTF-16BE or UTF-16-LE).
    BLOB 值是BLOB数据块,以输入的数据格式进行存储。如何输入就如何存储,不改 变格式。
    DATA 包含了 年份、月份、日期。
    TIME 包含了 小时、分钟、秒。

    SQLiteDatabase的常用方法

    方法名称 方法表示含义
    openOrCreateDatabase(String path,SQLiteDatabase.CursorFactory factory) 打开或创建数据库
    insert(String table,String nullColumnHack,ContentValues values) 插入一条记录
    delete(String table,String whereClause,String[] whereArgs) 删除一条记录
    query(String table,String[] columns,String selection,String[] selectionArgs,String groupBy,String having,String orderBy) 查询一条记录
    update(String table,ContentValues values,String whereClause,String[] whereArgs) 修改记录
    execSQL(String sql) 执行一条SQL语句
    close() 关闭数据库

    helper类

    这是一个辅助类,主要功能其实是帮助我们创建数据库,
    事实上创建数据库的操作,可以在操作数据库异常的情况下,去创建,但是这个工具类帮我我们完成了这件事情,并且只有第一次创建数据库的时候才会调用onCreate周期,所以如果我们有想要创建的数据库,一定要记得写在里面哦。
    public class MySqliteHelper extends SQLiteOpenHelper {
    
        private SQLiteDatabase sqLiteDatabase = null;
    
        public MySqliteHelper(Context context, String name, int version) {
            this(context, name, null, version);
        }
    
        public MySqliteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
            super(context, name, factory, version);
        }
    
        @Override
        public void onCreate(SQLiteDatabase sqLiteDatabase) {
            mkTable(User.class);
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    
        }
    }
    

    基本操作

    1.打开或者创建数据库

    直接创建时默认在/data/data/<包名>/databases/ 下,也可以自己自由选择位置,但是最好实在默认路径下,

    helper创建
    MySqliteHelper mySqliteHelper = new MySqliteHelper(this, "info.db", 1);
    
    直接创建
    db=SQLiteDatabase.openOrCreateDatabase("/data/data/com.lingdududu.db/databases/stu.db",null);
    
    2.创建表
    //创建表SQL语句
    String stu_table="create table usertable(_id integer primary key autoincrement,sname text,snumber text)";
    //执行SQL语句
    db.execSQL(stu_table);
    
    3.插入 insert
    方法1
    private void insert(SQLiteDatabase db){
    //实例化常量值
    ContentValues cValue = new ContentValues();
    //添加用户名
    cValue.put("sname","xiaoming");
    //添加密码
    cValue.put("snumber","01005");
    //调用insert()方法插入数据
    db.insert("stu_table",null,cValue);
    }
    
    方法2
    private void insert(SQLiteDatabase db){
    //插入数据SQL语句
    String stu_sql="insert into stu_table(sname,snumber) values('xiaoming','01005')";
    //执行SQL语句
    db.execSQL(sql);
    }
    
    4.删除 delete
    方法1
    private void delete(SQLiteDatabase db) {
    //删除条件
    String whereClause = "id=?";
    //删除条件参数
    String[] whereArgs = {String.valueOf(2)};
    //执行删除
    db.delete("stu_table",whereClause,whereArgs);
    }
    
    方法2
    private void delete(SQLiteDatabase db) {  
    //删除SQL语句  
    String sql = "delete from stu_table where _id = 6";  
    //执行SQL语句  
    db.execSQL(sql);  
    }  
    
    5.修改 update
    方法1
    private void update(SQLiteDatabase db) {  
    //实例化内容值 ContentValues values = new ContentValues();  
    //在values中添加内容  
    values.put("snumber","101003");  
    //修改条件  
    String whereClause = "id=?";  
    //修改添加参数  
    String[] whereArgs={String.valuesOf(1)};  
    //修改  
    db.update("usertable",values,whereClause,whereArgs);  
    }  
    
    方法2
    private void update(SQLiteDatabase db){  
    //修改SQL语句  
    String sql = "update stu_table set snumber = 654321 where id = 1";  
    //执行SQL  
    db.execSQL(sql);  
    } 
    
    6.查询数据
    关于query方法
    参数 含义
    参数table 表名称
    参数columns 列名称数组
    参数selection 条件字句,相当于where
    参数selectionArgs 条件字句,参数数组
    参数groupBy 分组列
    参数having 分组条件
    参数orderBy 排序列
    参数limit 分页查询限制
    参数Cursor 返回值,相当于结果集ResultSet
    关于cursor方法
    名称 含义
    getCount() 获得总的数据项数
    isFirst() 判断是否第一条记录
    isLast() 判断是否最后一条记录
    moveToFirst() 移动到第一条记录
    moveToLast() 移动到最后一条记录
    move(int offset) 移动到指定记录
    moveToNext() 移动到下一条记录
    moveToPrevious() 移动到上一条记录
    getColumnIndexOrThrow(String columnName) 根据列名称获得列索引
    getInt(int columnIndex) 获得指定列索引的int类型值
    getString(int columnIndex) 获得指定列缩影的String类型值
    第一种方法
    private void query(SQLiteDatabase db) {  
    //查询获得游标  
    Cursor cursor = db.query ("usertable",null,null,null,null,null,null);  
       
    //判断游标是否为空  
    if(cursor.moveToFirst() {  
    //遍历游标  
    for(int i=0;i<cursor.getCount();i++){  
    cursor.move(i);  
    //获得ID  
    int id = cursor.getInt(0);  
    //获得用户名  
    String username=cursor.getString(1);  
    //获得密码  
    String password=cursor.getString(2);  
    //输出用户信息 System.out.println(id+":"+sname+":"+snumber);  
    }  
    }  
    }
    
    第二种方法
    Cursor cursor = sqLiteDatabase.rawQuery("select * from User", null);
    

    个人封装的一点想法(只识别int与string)

    思路:
    1.仿照spring boot的操作,数据表基于bean对象创建,也是给予bean对象去实现一些基本操作。
    2.仿照gson形式,通过对于Class 对象的识别与操作,进行基本操作,避免大段大段的增删改查代码
    基本变量类
    public class User {
    
        public int a;
        public String username;
        public String password;
    
        public User(int a, String username, String password){
            this.a = a;
            this.username = username;
            this.password = password;
        }
    
        public User(){
    
        }
    }
    
    建立表的封装
    public void mkTable(Class c){
        Field[] fields = c.getFields();
        StringBuilder mktable = new StringBuilder("create table " +
                c.getSimpleName() +
                "(_id integer primary key autoincrement");
        for (Field field : fields){
            switch (field.getType().getName()){
                case "int":
                    mktable.append(',' + field.getName() + " integer");
                    break;
                case "java.lang.String":
                    mktable.append(',' + field.getName() + " text");
                    break;
            }
        }
        mktable.append(')');
        sqLiteDatabase.execSQL(mktable.toString());
    }
    
    //使用
    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        mkTable(User.class);
    }
    
    辅助查询类 传入:cursor Class 输出:list
    private List cursor2list(Cursor cursor, Class c){
        List<Object> list = new LinkedList<>();
        try {
            while (cursor.moveToNext()){
                Object o = c.newInstance();
                Field[] fields = c.getFields();
                for (int i = 1 ; i < cursor.getColumnCount(); i++){
                    switch (fields[i - 1].getType().getName()){
                        case "int":
                            fields[i - 1].setInt(o, cursor.getInt(i));
                            break;
                        case "java.lang.String":
                            fields[i - 1].set(o, cursor.getString(i));
                            break;
                    }
                }
                list.add(o);
                User user = (User) o;
                System.out.println(user.a + " " + user.username + " " + user.password);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }
    
    查询全部的封装
    public List getAll(Class c){
        Cursor cursor = sqLiteDatabase.rawQuery("select * from " + c.getSimpleName(), null);
        return cursor2list(cursor, c);
    }
    
    //使用
    mySqliteHelper.getAll(User.class);
    
    动态查询的封装
    public List query(Class c, String conditions){
        String string = "SELECT * from " + c.getSimpleName() + " where ";
        string += conditions;
        Cursor cursor = sqLiteDatabase.rawQuery(string, null);
        return cursor2list(cursor, c);
    }
    
    //使用
    mySqliteHelper.query(User.class, "username = '18xxxxxxxx7' and password='wewewewe'");
    
    清空数据表的封装
    public void clear(Class c){
        sqLiteDatabase.execSQL("delete from " + c.getSimpleName());
    }
    
    //使用
    mySqliteHelper.clear(User.class);
    
    条件删除的封装
    public void delete(Class c, String conditions){
        String string = "DELETE FROM " + c.getSimpleName() + " where ";
        string += conditions;
        System.out.println(string);
        sqLiteDatabase.execSQL(string);
    }
    
    //使用
    mySqliteHelper.delete(User.class, "username = '18xxxxxxxx7' and password='wewewewe'");
    
    更新的封装
    public void update(Class c, String results, String conditions){
        String string = "UPDATE " + c.getSimpleName() + " SET " + results +  " WHERE " + conditions;
        sqLiteDatabase.execSQL(string);
    }
    
    //使用
    mySqliteHelper.update(User.class, "username = '18xxxxxxxx7'", "username = '18xxxxxxx6'");
    

    结语

    关于数据库,个人一直觉得是一个很大的话题,很重,对我来说,很没有资格写一篇文章去认识它。
    很久之前就有过要使用的必要,但是当时做的很差,代码写的很乱,当然,现在依旧不整体。
    最近一直在整理Android相关的知识,数据库迟迟不能下手,整理出简单的知识点很容易,但是理解出一种最正确的用法很难。
    尤其是最近思考到很多问题,内存泄漏,对象直接存储二进制文件,本地直接存储有格式的文本是否也是一种可用的方式。
    思考了很多,感觉很多条路,很多种选择,但是要整理能继续下去,数据库是必须面对的,哪怕自己做的不好,没有自己的理解。
    还有Android事件分发,内存泄漏,弱引用的使用,网络知识相关,事件分发感觉自己用起来还行,但是当想要说出来的时间感觉很难,没有一个核心。剩下的东西,感觉真的是一团雾水,这几种东西,想到弄清本质,确实是需要去看看书,阅读一下了,希望几天之后,我就可以有自己对于这些的认识,继续整理下去,这几天轻松整理些基本View相关吧,也写写一些自己感兴趣的小控件。

    相关文章

      网友评论

        本文标题:持久化存储---Sqlite的初步认识

        本文链接:https://www.haomeiwen.com/subject/xrdtrftx.html