Android SQLite

一、使用SQLiteOpenHelper类创建数据库与版本管理


    1、nCreate(database):首次使用软件时生成数据库表
    2、onUpgrade(database,oldVersion,newVersion):在数据库的版本发生变化时会被调用, 一      般   在软件升级时才需改变版本号,而数据库的版本是由程序员控制的

public class MyDBOpenHelper extends SQLiteOpenHelper {
    public MyDBOpenHelper(Context context, String name, CursorFactory factory,
            int version) {super(context, "my.db", null, 1); }
    @Override
    //数据库第一次创建时被调用
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE person(personid INTEGER PRIMARY KEY AUTOINCREMENT,name VARCHAR(20))");
        
    }
    //软件版本号发生改变时调用
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("ALTER TABLE person ADD phone VARCHAR(12) NULL");
    }
}

当调用的MyDBOpenhelper的对象的getWritableDatabase()就会在下述目录下创建我们的db 数据库文件:

可以使用SQLite图形化工具(SQLite Expert )查看db文件

二、Demo

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Context mContext;
    private Button btn_insert;
    private Button btn_query;
    private Button btn_update;
    private Button btn_delete;
    private SQLiteDatabase db;
    private MyDBOpenHelper myDBHelper;
    private StringBuilder sb;
    private int i = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = MainActivity.this;
        myDBHelper = new MyDBOpenHelper(mContext, "my.db", null, 1);
        bindViews();
    }

    private void bindViews() {
        btn_insert = (Button) findViewById(R.id.btn_insert);
        btn_query = (Button) findViewById(R.id.btn_query);
        btn_update = (Button) findViewById(R.id.btn_update);
        btn_delete = (Button) findViewById(R.id.btn_delete);

        btn_query.setOnClickListener(this);
        btn_insert.setOnClickListener(this);
        btn_update.setOnClickListener(this);
        btn_delete.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        db = myDBHelper.getWritableDatabase();
        switch (v.getId()) {
            case R.id.btn_insert:
                ContentValues values1 = new ContentValues();
                values1.put("name", "呵呵~" + i);
                i++;
                //参数依次是:表名,强行插入null值得数据列的列名,一行记录的数据
                db.insert("person", null, values1);
                Toast.makeText(mContext, "插入完毕~", Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_query:
                sb = new StringBuilder();
                //参数依次是:表名,列名,where约束条件,where中占位符提供具体的值,指定group by的列,进一步约束
                //指定查询结果的排序方式
                Cursor cursor = db.query("person", null, null, null, null, null, null);
                if (cursor.moveToFirst()) {
                    do {
                        int pid = cursor.getInt(cursor.getColumnIndex("personid"));
                        String name = cursor.getString(cursor.getColumnIndex("name"));
                        sb.append("id:" + pid + ":" + name + "\n");
                    } while (cursor.moveToNext());
                }
                cursor.close();
                Toast.makeText(mContext, sb.toString(), Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_update:
                ContentValues values2 = new ContentValues();
                values2.put("name", "嘻嘻~");
                //参数依次是表名,修改后的值,where条件,以及约束,如果不指定三四两个参数,会更改所有行
                db.update("person", values2, "name = ?", new String[]{"呵呵~2"});
                break;
            case R.id.btn_delete:
                //参数依次是表名,以及where条件与约束
                db.delete("person", "personid = ?", new String[]{"3"});
                break;
        }
    }
}

三、使用SQL语句操作数据库,QLiteDatabase提供的相关方法:

  • execSQL(SQL,Object[]):使用带占位符的SQL语句,这个是执行修改数据库内容的sql语句用的
  • rawQuery(SQL,Object[]):使用带占位符的SQL查询操作 另外前面忘了介绍下Curosr这个东西以及相关属性,这里补充下: ——Cursor对象有点类似于JDBC中的ResultSet,结果集!使用差不多,提供一下方法移动查询结果的记录指针:
  • move(offset):指定向上或者向下移动的行数,整数表示向下移动;负数表示向上移动!
  • moveToFirst():指针移动到第一行,成功返回true,也说明有数据
  • moveToLast():指针移动到最后一样,成功返回true;
  • moveToNext():指针移动到下一行,成功返回true,表明还有元素!
  • moveToPrevious():移动到上一条记录
  • getCount( )获得总得数据条数
  • isFirst():是否为第一条记录
  • isLast():是否为最后一项
  • moveToPosition(int):移动到指定行

1.插入数据:

public void save(Person p)
{
    SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
    db.execSQL("INSERT INTO person(name,phone) values(?,?)",
                new String[]{p.getName(),p.getPhone()});
}

2.删除数据:

public void delete(Integer id)
{
    SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
    db.execSQL("DELETE FROM person WHERE personid = ?",
                new String[]{id});
}

3.修改数据:

public void update(Person p)
{
    SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
    db.execSQL("UPDATE person SET name = ?,phone = ? WHERE personid = ?",
        new String[]{p.getName(),p.getPhone(),p.getId()});
}

4.查询数据:

public Person find(Integer id)
{
    SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
    Cursor cursor =  db.rawQuery("SELECT * FROM person WHERE personid = ?",
            new String[]{id.toString()});
    //存在数据才返回true
    if(cursor.moveToFirst())
    {
        int personid = cursor.getInt(cursor.getColumnIndex("personid"));
        String name = cursor.getString(cursor.getColumnIndex("name"));
        String phone = cursor.getString(cursor.getColumnIndex("phone"));
        return new Person(personid,name,phone);
    }
    cursor.close();
    return null;
}

5.数据分页:

public List<Person> getScrollData(int offset,int maxResult)
{
    List<Person> person = new ArrayList<Person>();
    SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
    Cursor cursor =  db.rawQuery("SELECT * FROM person ORDER BY personid ASC LIMIT= ?,?",
        new String[]{String.valueOf(offset),String.valueOf(maxResult)});
    while(cursor.moveToNext())
    {
        int personid = cursor.getInt(cursor.getColumnIndex("personid"));
        String name = cursor.getString(cursor.getColumnIndex("name"));
        String phone = cursor.getString(cursor.getColumnIndex("phone"));
        person.add(new Person(personid,name,phone)) ;
    }
    cursor.close();
    return person;
}

6.查询记录数:

public long getCount()
{
    SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
    Cursor cursor =  db.rawQuery("SELECT COUNT (*) FROM person",null);
    cursor.moveToFirst();
    long result = cursor.getLong(0);
    cursor.close();
    return result;   
    //除了上面获取条数的方法外还可以使用cursor.getCount()方法获得数据的条数, 但是SQL语句要改     改!比如SELECT * FROM person;   
}   

四、事务

SQLiteDatabase mydb = myDBHelper.getWritableDatabase();
mydb.beginTransaction();//开启事务
  try {
        mydb.execSQL("update person set adress = ? where personid=?",
                   new String[]{"呼呼家~" + i,"20000"});
        mydb.execSQL("INSERT INTO person(name,phone) values(?,?)",
                   new String[]{"噜噜~" + i,"phone"+i});
        mydb.setTransactionSuccessful();//提交事务
    }finally {
        mydb.endTransaction();//结束事务
    }


五、SimpleCursorAdapter绑定数据库数据

六、数据库版本升级

假如我们已经升级到第三个版本了,我们在第二个版本增加了一个表, 然后第三个版本也增加了一个表,加入用户直接从第一个版本升级到第三个版本,这样 没经过第二个版本,就没有增加的那个表....?

public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource,
            int arg2, int arg3) {
    switch(arg2){
        case 1:
            db.execSQL(第一个版本的建表语句);
        case 2:
            db.execSQL(第二个版本的建表语句);
        case 3:
            db.execSQL(第三个版本的建表语句); 
    }
}
这里并没有写break,这就对了,这是为了保证跨版本升级时,每次数据库 修改都能全部执行到!这样可以保证表结构都是最新的!


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/546956.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

20240328-2-随机森林面试题RandomForest

随机森林面试题 1. 简单介绍随机森林 一种基于树模型的Bagging的优化版本&#xff0c;一棵树的生成肯定还是不如多棵树&#xff0c;因此就有了随机森林&#xff0c;解决决策树泛化能力弱的特点。 多次随机取样&#xff0c;多次随机取属性&#xff0c;选取最优分割点&#xff…

在Vue3中如何使用H.265视频流媒体播放器EasyPlayer.js?

H5无插件流媒体播放器EasyPlayer属于一款高效、精炼、稳定且免费的流媒体播放器&#xff0c;可支持多种流媒体协议播放&#xff0c;可支持H.264与H.265编码格式&#xff0c;性能稳定、播放流畅&#xff0c;能支持WebSocket-FLV、HTTP-FLV&#xff0c;HLS&#xff08;m3u8&#…

【uniapp踩坑记】——微信小程序转发保存图片

关于微信小程序转发&保存图片 微信小程序图片转发保存简单说明网络图片的转发保存base64流形式图片转发保存 已经好多年没写博客了&#xff0c;最近使用在用uniapp开发一个移动版管理后台&#xff0c;记录下自己踩过的一些坑 吃相别太难看&#xff0c;搞一堆下头僵尸号来点…

【YOLOv9】使用yolov9训练自己的数据集/验证 /推理 /参数分析

完胜V8的SOTA模型Yolov9(论文阅读笔记)内容 点击即可跳转 当今的YOLO系列武林盟主YOLOV9&#xff1a; YOLOv9的优秀表现&#xff1a; 环境&#xff1a; ubuntu20.04&#xff0c;无GPU&#xff0c;使用anaconda3创建的虚拟环境yolov9。 环境安装&#xff1a; conda create -n …

JavaSE图书管理系统

JavaSE图书管理系统 思路一.Main方法二.User包1.User类2.NormaUser类3.AdminUser类三.book包1.BookList类2.Book类四.operation包1.IOPeration接口2.AddOperation类新增图书3.BorrowOperation类借阅图书4.DelOperation类删除图书5.FindOperation类查找图书6.ReturnOperation类归…

Centos7配置IP地址

1、找到网卡名字 使用root用户登陆&#xff0c;输入命令 ifconfig 2、打开配置文件 输入命令&#xff0c;打开配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens33 3、添加IP地址 3.1修改BOOTPROTO 将“BOOTPROTOdhcp” 改为 “BOOTPROTOstatic” 3.2添加IP地址 在配…

【JavaEE多线程】从单例模式到线程池的深入探索

目录 多线程案例单例模式阻塞队列定时器线程池总结-保证线程安全的思路对比线程和进程 多线程案例 单例模式 单例模式是一种设计模式 设计模式&#xff0c;就是程序员的棋谱&#xff0c;这里介绍了很多典型场景&#xff0c;以及典型场景的处理方式&#xff0c;按照设计模式写…

火车头采集一键发布到Zblog

火车头采集发布到Zblog系统&#xff0c;主要操作步骤如下&#xff1a; 目录 1、Zblog火车头Web发布模块 2、内容发布参数映射&#xff0c;火车头发布到Zblog 3、简数一键发布到Zblog方法 1、Zblog火车头Web发布模块 自行编写Zblog火车头Web发布模块&#xff0c;一般要使用f…

Linux--进程间的通信--进程池

进程间的通信–匿名管道 进程池的概念 进程池是一种将多个进程组织起来以执行特定任务的机制。它由多个预先创建好的资源进程和一个管理进程组成。这些资源进程被管理进程负责分配和调度&#xff0c;用于处理任务。 当有新的任务提交时&#xff0c;管理进程会从进程池中取出一…

2024北京门窗展|2024北京门窗展会|2024北京门窗展览会

CWE中国&#xff08;北京&#xff09;国际系统门窗及幕墙博览会 CWE China&#xff08;Beijing&#xff09;International System Doors Windows and Curtain Walls Expo 2024年8月29-31日 北京&#xff0c;中国国际展览中心顺义馆 展会概况&#xff1a; 2024年CWE中国&…

【Unity】ScriptableObject 在游戏中的使用实例

ScriptableObject 在游戏中的使用实例 ScriptableObject 使用指南Unity 存储游戏数据的几种方法Unity ScriptableObject实例创建一个物品管理的ScriptableObject创建一个管理所有 ScriptableObject 的数据库&#xff08;ItemDBSO&#xff09; ScriptableObject 使用指南 Scrip…

回溯算法练习day.2

216.组合总和III 链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 找出所有相加之和为 n 的 k 个数的组合&#xff0c;且满足下列条件&#xff1a; 只使用数字1到9每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相…

基于STM32的RFID智能门锁系统

本文针对RFID技术&#xff0c;着重研究了基于单片机的智能门锁系统设计。首先&#xff0c;通过链接4*4按键模块与主控STM32&#xff0c;实现了多种模式&#xff0c;包括刷卡开锁、卡号权限管理、密码开锁、修改密码、显示实时时间等功能。其次&#xff0c;采用RC522模块与主控S…

【C语言基础】:预处理详解(二)

文章目录 一、宏和函数的对比二、#和##运算符2.1 #运算符2.2 ##运算符 三、#undef四、命令行定义五、条件编译六、头文件的包含1. 头文件包含的方式2. 嵌套文件包含 上期回顾&#xff1a; 【C语言基础】&#xff1a;预处理详解(一) 一、宏和函数的对比 宏通常被应有于执行简单…

Vue3---基础10(路由)

写一个最基本的路由导航 下载、创建、使用路由 下载路由 npm i vue-router 创建路由 先在 src 内去创建一个 router 文件夹 在文件夹内创建一个 index 文件 index.ts 内代码 // 创建一个路由器&#xff0c;并暴露出去 // 引入createRouter import { createRouter, createWeb…

CSS使用自己的字体

在项目的根目录下的static文件夹中放置字体文件。在项目中使用这个字体&#xff0c;需要2个步骤。 一. 你需要在全局样式文件中引入它。 假设你的全局样式文件是App.vue或者App.vue中引入的App.scss文件&#xff0c;你可以像这样引入字体文件&#xff1a; font-face {font-fa…

深度学习体系结构——CNN, RNN, GAN, Transformers, Encoder-Decoder Architectures算法原理与应用

1. 卷积神经网络 卷积神经网络&#xff08;CNN&#xff09;是一种特别适用于处理具有网格结构的数据&#xff0c;如图像和视频的人工神经网络。可以将其视作一个由多层过滤器构成的系统&#xff0c;这些过滤器能够处理图像并从中提取出有助于进行预测的有意义特征。 设想你手…

MySQL中的存储过程详解(上篇)

使用语言 MySQL 使用工具 Navicat Premium 16 代码能力快速提升小方法&#xff0c;看完代码自己敲一遍&#xff0c;十分有用 拖动表名到查询文件中就可以直接把名字拉进来中括号&#xff0c;就代表可写可不写 目录 1.认识存储过程 1.1 存储过程的作用 1.2 存储过程简介…

C#基础|数据类型、变量

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 01 数据类型 数据类型是为了方便存储数据的&#xff0c;为了将数据按照不同的分类存储&#xff0c;所以引入数据类型。这个在PLC中已经很熟悉了。 数据类型的作用&#xff1a;就是为了更好地管理内存&#xff0c;为…

顺序表 (头删 尾删 清空)

//头删 | 1 #include "head.h" | 1 #ifndef ww87 void head_del(p lp) | 2 int main(int argc, const char *argv[]) …