原文链接:http://www.orlion.ga/610/

一、事务

SQLite支持事务,看一下Android如何使用事务:比如 Book表中的数据都已经很老了,现在准备全部废弃掉替换成新数据,可以先使用delete()方法将Book表中的数据删除, 然后再使用insert()方法将新的数据添加到表中。我们要保证的是,删除旧数据和添加新数据的操作必须一起完成,否则就还要继续保留原来的旧数据。

                Button replaceData = (Button) findViewById(R.id.replace_data);replaceData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {SQLiteDatabase db = dbHelper.getWritableDatabase();db.beginTransaction();db.delete("book", null, null);try {if (true) {// 手动抛出异常,让事务失败throw new Exception();}ContentValues values = new ContentValues();values.put("name", "book new");values.put("author", "orlion");values.put("pages", 200);values.put("price", 100);db.insert("book", null, values);db.setTransactionSuccessful(); // 事务已经执行成功} catch (Exception e) {e.printStackTrace();} finally {db.endTransaction(); // 结束事务}}});

上述代码就是Android中事务的标准用法, 首先调用SQLiteDatabase的beginTransaction()方法来开启一个事务,然后在一个异常捕获的代码块中去执行具体的数据库操作,当所有的操作都完成之后,调用 setTransactionSuccessful()表示事务已经执行成功了,最后在 finally代码块中调用 endTransaction()来结束事务。注意观察,我们在删除旧数据的操作完成后手动抛出了一个 NullPointerException,这样添加新数据的代码就执行不到了。不过由于事务的存在,中途出现异常会导致事务的失败,此时旧数据应该是删除不掉的。

二、升级数据库的最佳写法

// 这里直接复制《第一行代码原文》

Android入门(十)SQLite创建升级数据库 一文中升级数据库的方式是非常粗暴的,为了保证数据库中的表是最新的,我们只是简单地在 onUpgrade()方法中删除掉了当前所有的表,然后强制重新执行了一遍 onCreate()方法。这种方式在产品的开发阶段确实可以用,但是当产品真正上线了之后就绝对不行了。

每一个数据库版本都会对应一个版本号, 当指定的数据库版本号大于当前数据库版本号的时候, 就会进入到 onUpgrade()

方法中去执行更新操作。这里需要为每一个版本号赋予它各自改变的内容,然后在onUpgrade()方法中对当前数据库的版本号进行判断,再执行相应的改变就可以了。

接着就让我们来模拟一个数据库升级的案例,还是由 MyDatabaseHelper类来对数据库进行管理。第一版的程序要求非常简单,只需要创建一张 Book表,MyDatabaseHelper中的代码如下所示:

public class MyDatabaseHelper extends SQLiteOpenHelper {public static final String CREATE_BOOK = "create table Book ("+ "id integer primary key autoincrement, "+ "author text, "+ "price real, "+ "pages integer, "+ "name text)";public MyDatabaseHelper(Context context, String name, CursorFactoryfactory, int version) {super(context, name, factory, version);}@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL(CREATE_BOOK);}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
}

不过,几星期之后又有了新需求,这次需要向数据库中再添加一张 Category表。于是,修改 MyDatabaseHelper中的代码,如下所示:

public class MyDatabaseHelper extends SQLiteOpenHelper {public static final String CREATE_BOOK = "create table Book ("+ "id integer primary key autoincrement, "+ "author text, "+ "price real, "+ "pages integer, "+ "name text)";public static final String CREATE_CATEGORY = "create table Category ("+ "id integer primary key autoincrement, "+ "category_name text, "+ "category_code integer)";public MyDatabaseHelper(Context context, String name,CursorFactory factory, int version) {super(context, name, factory, version);}@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL(CREATE_BOOK);db.execSQL(CREATE_CATEGORY);}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {switch (oldVersion) {case 1:db.execSQL(CREATE_CATEGORY);default:}}
}

可以看到,在 onCreate()方法里我们新增了一条建表语句,然后又在 onUpgrade()方法中添加了一个 switch判断,如果用户当前数据库的版本号是 1,就只会创建一张 Category表。这样当用户是直接安装的第二版的程序时,就会将两张表一起创建。而当用户是使用第二版的程序覆盖安装第一版的程序时,就会进入到升级数据库的操作中,此时由于 Book表已经存在了,因此只需要创建一张 Category表即可。但是没过多久,新的需求又来了,这次要给 Book表和 Category表之间建立关联,需要在 Book表中添加一个 category_id的字段。 再次修改 MyDatabaseHelper中的代码, 如下所示:

public class MyDatabaseHelper extends SQLiteOpenHelper {public static final String CREATE_BOOK = "create table Book ("+ "id integer primary key autoincrement, "+ "author text, "+ "price real, "+ "pages integer, "+ "name text, "+ "category_id integer)";public static final String CREATE_CATEGORY = "create table Category ("+ "id integer primary key autoincrement, "+ "category_name text, "+ "category_code integer)";public MyDatabaseHelper(Context context, String name,CursorFactory factory, int version) {super(context, name, factory, version);}@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL(CREATE_BOOK);db.execSQL(CREATE_CATEGORY);}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {switch (oldVersion) {case 1:db.execSQL(CREATE_CATEGORY);case 2:db.execSQL("alter table Book add column category_id integer");default:}}
}

可以看到,首先我们在 Book表的建表语句中添加了一个 category_id列,这样当用户直接安装第三版的程序时,这个新增的列就已经自动添加成功了。然而,如果用户之前已经安装了某一版本的程序,现在需要覆盖安装,就会进入到升级数据库的操作中。在 onUpgrade()方法里,我们添加了一个新的 case,如果当前数据库的版本号是 2,就会执行 alter命令来为Book表新增一个 category_id列。

这里请注意一个非常重要的细节,switch中每一个 case的最后都是没有使用 break的,为什么要这么做呢?这是为了保证在跨版本升级的时候, 每一次的数据库修改都能被全部执行到。比如用户当前是从第二版程序升级到第三版程序的,那么 case 2中的逻辑就会执行。而如果用户是直接从第一版程序升级到第三版程序的,那么 case 1和 case 2中的逻辑都会执行。使用这种方式来维护数据库的升级,不管版本怎样更新,都可以保证数据库的表结构是最新的,而且表中的数据也完全不会丢失了。

转载于:https://www.cnblogs.com/orlion/p/5350683.html

Android入门(十二)SQLite事务、升级数据库相关推荐

  1. 网络编程懒人入门(十二):快速读懂Http/3协议,一篇就够!

    本文中文译文由作者"ably.io"发布于公众号"高可用架构",译文原题:<深入解读HTTP3的原理及应用>.英文原题:<HTTP/3 dee ...

  2. android 入门 006(sqlite增删改查)

    android 入门 006(sqlite增删改查) package cn.rfvip.feb_14_2_sqlite;import android.content.Context; import a ...

  3. Android Studio(十二):打包多个发布渠道的apk文件

    Android Studio相关博客: Android Studio(一):介绍.安装.配置 Android Studio(二):快捷键设置.插件安装 Android Studio(三):设置Andr ...

  4. IM开发者的零基础通信技术入门(十二):上网卡顿?网络掉线?一文即懂!

    [来源申明]本文引用了微信公众号"鲜枣课堂"的<上网慢?经常掉线?这篇文章告诉你该怎么办!>文章内容.为了更好的内容呈现,即时通讯网在引用和收录时内容有改动,转载时请注 ...

  5. android入门基础笔记,Sqlite数据库下载

    * 移动通讯技术的发展: 第一代通讯技术:模拟信号 工作频段   缺点:保密性差 第二代通讯技术: 体积越来越小  数字信号(加密)   短信  彩信 第三代通讯技术: 数字信号   可处理图像.音乐 ...

  6. Android 第十二课 使用LitePal操作数据库(记得阅读最后面的注意事项哦)

    一.LitePal简介 1.(新建项目LitePalTest) 正式接触第一个开源库---LitePal LitePal是一款开源的Android 数据库框架,它采用了对象关系映射(ORM)的模式. ...

  7. 第十二章:Qt数据库(sqlite)

    回顾: 第一章:Qt的概述 第二章:在Ubuntu编写第一个Qt程序 第三章:Qt的字符串和字符编码 第四章:Qt的信号和槽 第五章:Qt容器窗口(父窗口) 第六章:面向对象的Qt编程 第七章:Qt设 ...

  8. JavaWeb学习总结(十二)--事务

    一.事务的介绍 1.1 什么是事务 银行转账!张三转10000块到李四的账户,这其实需要两条SQL语句: 给张三的账户减去10000元: 给李四的账户加上10000元. 如果在第一条SQL语句执行成功 ...

  9. Android入门篇二:使用意图在Activity之间传递数据

    首先,在这里稍微介绍一下意图(Intent)的概念: Intent(意图)主要是解决Android应用的各项组件之间的通讯. Intent 负责对应用中一次操作的动作.动作涉及数据.附加数据进行描述, ...

最新文章

  1. python isinstance函数
  2. unity全栈开发是什么意思_unity游戏公司面试问题总结
  3. C语言(CED)钢条最优切割收益
  4. Yarn 国内加速,修改镜像源
  5. extjs Grid (二)
  6. 湖南工大c语言上机题库,湖南科技大学2010年C语言上机题库
  7. Mac安装 MySQL 可视化工具MySQL Workbench
  8. 关于安装VC++运行库遇到各种小问题
  9. python-docx 复制一页_python 怎么用docx读取word的某一页然后放到新的word文档中?...
  10. 史上最全运放运算放大器知识讲解
  11. u盘chk文件恢复图文教程
  12. HDU - 1234 开门人和关门人
  13. python 等腰三角形的性质_Blender 脚本之 Operator 初探
  14. 入职腾讯第九年,我辞职了
  15. 人工智能与数据挖掘的关系
  16. linux下输入ls显示时间格式,【Linux基础】linux下修改ls显示的时间格式
  17. 科研人快速入门LaTex到日常使用,下载安装配置,语法使用说明等
  18. Simulink三相异步电机仿真
  19. 网络对抗 Exp5 MSF基础应用 20154311 王卓然
  20. YOLOV3—进行车辆检测

热门文章

  1. python二十六: 字符串颜色
  2. MySQL 表分区详解MyiSam引擎和InnoDb 区别(实测)
  3. 按阅读习惯来高效排列字符串的脚本
  4. VBS脚本常用经典代码收集
  5. 单个APP接入多个微信支付宝支付的一种解决方案
  6. 将weex项目打包的关键点
  7. DataGridView和DataTable同步排序
  8. Tomcat 配置WEB虚拟映射 及 配置虚拟主机
  9. 【ASP.NET开发】ASP.NET(MVC)三层架构知识的学习总结
  10. .NET 部署-03Web Deployment项目-05自定义Web Deployment项目