`
huiqinbo
  • 浏览: 344703 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

无废话Android 系列教程35 [Android下的数据库SQLite事务概念及使用&&测试]

 
阅读更多

1. 事务的作用:我们在一些特殊业务需要时。会有如果要求:要保证一个操作要么同时成功,要么同时失败;不允许上个逻辑成功后突然出错/异常(如空指针异常),导致下一个操作失败,这是绝对不允许的。

 

2. 事务经典实例:如银行转帐业务,A用户转出100元给B用户,这时要么A用户少100元 B用户同时多100元;或转帐失败,A用户钱没减少B用户钱也没增加,提示用户转帐失败;不允许A用户钱少100元后,由于某些异常导致B用户没收到100元钱。

 

3. com.andy.shiwu 包下的PersonSQLiteOpenHelper.java

package com.andy.shiwu;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

/**
 * 创建PersonSQLiteOpenHelper类 继承SQLiteOpenHelper抽象类,此时必须创建构造方法
 * @author huiqinbo
 *
 */
public class PersonSQLiteOpenHelper extends SQLiteOpenHelper {

	//通过getSimpleName()方法获取到值为"PersonSQLiteOpenHelper"
	private static final String tag = PersonSQLiteOpenHelper.class.getSimpleName();

	/**
	 * 数据库的构造方法, 用来定义数据库的名称/数据库的查询结果集/数据库的版本号
	 * 
	 * 当版本号发生变化时才可以调用onUpgrade方法; 如版本号从1 →2
	 * @param context
	 * @param name
	 * @param factory
	 * @param version
	 */
	public PersonSQLiteOpenHelper(Context context) {
//		super(context, "person.db", null, 1);
		super(context, "person.db", null, 4);
		// TODO Auto-generated constructor stub
	}
	
	

	/**
	 * 数据库第一次被创建的时候调用的方法
	 * @param db 被创建的数据库
	 */
	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL("create table person (id integer primary key autoincrement, name varchar(20), number varchar(20))");
	}

	
	/**
	 * sqlite中ALTER TABLE语句不支持DROP COLUMN,只有RENAME 和ADD 语句.
	 */
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		// TODO Auto-generated method stub
		Log.i(tag, "数据库的版本发生变化了");
		db.execSQL("alter table person add account varchar(20)");

	}

}

 

注:请关注 51  52行,这里更改数据库person的表结构,增加了account字段!

 

4. com.andy.shiwu.dao包下面的PersonDao2.java

 

package com.andy.shiwu.dao;

import java.util.ArrayList;
import java.util.List;

import com.andy.shiwu.PersonSQLiteOpenHelper;
import com.andy.shiwu.domain.Person;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class PersonDao2 {
	private PersonSQLiteOpenHelper helper;
	public PersonDao2(Context context){
		helper = new PersonSQLiteOpenHelper(context);
	}
	
	/*
	 * 插入用户名和手机号到SQLite数据库
	 * 
	 * the row ID of the newly inserted row, or -1 if an error occurred
	 */
	public long addPerson(String name, String number,int account){
		
		//此时就获取到了数据库
		SQLiteDatabase db = helper.getWritableDatabase();
		//db.execSQL("insert into person (name,number) values (?,?)", new Object[]{name,number});
		ContentValues values = new ContentValues();
		values.put("name", name);
		values.put("number", number);
		values.put("account", account);
		long row_id = db.insert("person", null, values);
		db.close();
		return row_id;
	}
	
	/**
	 * 删除一条数据,按用户名的条件
	 * @param name
	 * 
	 * WhereClause :the optional WHERE clause to apply when deleting. Passing null will delete all rows.
	 */
	public int deletePerson(String name){
		SQLiteDatabase db = helper.getWritableDatabase();
//		db.execSQL("delete from person where name =?", new Object[]{name});
		int row_id = db.delete("person", "name=?", new String[]{name});
		db.close();
		
		return row_id;
	}
	
	
	/**
	 * 修改一条数据,按用户名的条件
	 * @param name
	 * @param number
	 */
	public int updatePerson(String name, String number){
		SQLiteDatabase db = helper.getWritableDatabase();
//		db.execSQL("update person set number = ? where name = ?", new Object[]{name,number} );
		ContentValues values = new  ContentValues();
		values.put("number", number);
		
		int row_id = db.update("person", values, "name=?", new String[]{name});
		db.close();
		
		return row_id;
	}
	
	/**
	 * 查询一条数据,按用户名的条件
	 * @param name
	 * @param number
	 * selection : A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given table.
	 * selectionArgs:  You may include ?s in selection, which will be replaced by the values from selectionArgs, in order that they appear in the selection. The values will be bound as Strings.
	 */
	public boolean findPerson(String name){
		SQLiteDatabase db = helper.getWritableDatabase();
//		Cursor cursor = db.rawQuery("select * from person where name=?", new String[]{name});
		Cursor cursor = db.query("person", new String[]{"id", "name", "number"}, "name=?", new String[]{name}, null, null, null);
		boolean result = cursor.moveToNext();
		cursor.close();
		db.close();
		return result;
	}
	
	
	public List<Person> findAllPerson(){
		SQLiteDatabase db = helper.getWritableDatabase();
//		Cursor cursor = db.rawQuery("select * from person", null);
		Cursor cursor = db.query("person", new String[]{"id","name","number"}, null, null, null, null, null);
		List<Person> persons = new ArrayList<Person>(); 
		Person person;
		while(cursor.moveToNext()){
			int id = cursor.getInt(cursor.getColumnIndex("id"));
			String name = cursor.getString(cursor.getColumnIndex("name"));
			String number = cursor.getString(cursor.getColumnIndex("number"));
			person = new Person(id,name,number);
			persons.add(person);
		}
		cursor.close();
		db.close();
		return persons;
	}

}
 

 

5. com.andy.shiwu.domain 包下的Person.java 类

 

package com.andy.shiwu.domain;

public class Person {
	private int id;
	private String name;
	private String number;
	
	public Person(int id, String name, String number){
		this.id = id;
		this.name= name;
		this.number = number;
	}
	
	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + ", number=" + number
				+ "]";
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getNumber() {
		return number;
	}
	public void setNumber(String number) {
		this.number = number;
	}
	
	

}
 

 

6. com.andy.shiwu.test 包下的TestPersonDao2.java

 

package com.andy.shiwu.test;

import java.util.List;

import com.andy.shiwu.PersonSQLiteOpenHelper;
import com.andy.shiwu.dao.PersonDao2;
import com.andy.shiwu.domain.Person;

import android.database.sqlite.SQLiteDatabase;
import android.test.AndroidTestCase;
import android.util.Log;

/**
 * 
 * @author huiqinbo
 *
 */
public class TestPersonDao2 extends AndroidTestCase {

	private static final String tag = TestPersonDao2.class.getSimpleName();
	public PersonDao2 pd;

	/**
	 * getContext() 是测试框架给提供的上下文件 来源:android.test.AndroidTestCase.getContext()
	 * 
	 * 第一次执行时调用PersonSQLiteOpenHelper.java 内的onCreate方法,
	 * 当版本号发生变化时,会调用PersonSQLiteOpenHelper.java 内的onUpgrade方法.
	 */
	public void testCreatePersonDb() {
		PersonSQLiteOpenHelper db = new PersonSQLiteOpenHelper(getContext());
		// 打开或创建一个可写的数据库
		db.getWritableDatabase();
	}

	public void testAddPerson() {
		pd = new PersonDao2(getContext());
		pd.addPerson("张三", "123456789", 5000);
		pd.addPerson("李四", "987654321", 10000);
	}



	/**
	 * 这是没有加上事务的方法.
	 */
	public void testTransaction() {
		PersonSQLiteOpenHelper helper = new PersonSQLiteOpenHelper(getContext());
		// 打开或创建一个可写的数据库
		SQLiteDatabase db = helper.getWritableDatabase();
		db.execSQL("update person set account=account-1000 where name ='张三'");
		db.execSQL("update person set account=account+1000 where name ='李四'");
		db.close();
	}

	/*
	 * 这是加上事务的方法. 假如在执行到"张三"SQL语句执行成功了,到李四SQL语句执行前出现了异常,导致李四操作没成功,这是不可以的。
	 * 所以要使用「事务」,要么同时成功,要么同时失败.
	 */
	public void testTransactionShiWu() {
		PersonSQLiteOpenHelper helper = new PersonSQLiteOpenHelper(getContext());
		// 打开或创建一个可写的数据库
		SQLiteDatabase db = helper.getWritableDatabase();
		
//		String s = null;
		//1. 开启数据库的事务
		db.beginTransaction();
		try {
			db.execSQL("update person set account=account-1000 where name ='张三'");
//			s.equals("这里是制造空指针异常语句,与事务无关!");
			db.execSQL("update person set account=account+1000 where name ='李四'");
			
			
			//2. 标记当前数据库事务执行成功.
			//(当认为事务执行成功时,就必须执行db.setTransactionSuccessful(), 如果不执行这段代码,默认情况认为执行失败,数据就不会不commit, 如果commit会回滚roll back)
			//通过Andy个人实验确实是:当没有setTransactionSuccessful这个方法时张三&李四的操作同时不成功
			db.setTransactionSuccessful();
		} catch (Exception e){
			Log.i(tag, "事务中代码内出现异常, 请检查");
		}
		finally {
			
			//3. 结束数据库的事务
			//通过Andy个人实验确实是:当没有setTransactionSuccessful这个方法时张三&李四的操作同时不成功
			//它会检查如果前面有db.setTransactionSuccessful() 它会commit数据,否则会rolled back回滚数据
			db.endTransaction();
			db.close();
		}
	}
}
 

 

 7.  使用adb 测试数据库

 

 

 

 8 . 源代码,请参照附件

  • 大小: 172.8 KB
分享到:
评论

相关推荐

    无废话Android 系列教程33 [Adroid下SQLite数据库增删改查&测试]

    本教程将深入讲解如何在Android环境下进行SQLite数据库的增删改查操作以及相关的测试方法。 首先,我们需要创建一个SQLite数据库。在Android中,我们通常通过继承SQLiteOpenHelper类来实现这个功能。...

    Android数据库SQLite详解

    本文将深入探讨SQLite在Android中的使用,包括基本概念、数据库操作以及实际应用示例。 ### 1. SQLite基本概念 - **数据库**: 数据库是存储和组织数据的结构化系统,SQLite在Android中表现为一个数据库文件,扩展...

    无废话Android 系列教程34 [使用系统api实现SQLite增删改查&&测试]

    本教程将深入探讨如何使用系统API实现SQLite数据库的增删改查操作,并进行相关的测试。以下是对这个主题的详细讲解: 一、SQLite数据库基础 SQLite是Android系统内置的SQL数据库引擎,无需单独安装。开发者可以创建...

    Android源码——数据库SQLite.zip

    总的来说,"Android源码——数据库SQLite.zip"的内容涵盖了SQLite在Android中的使用、数据库的创建与管理、SQL操作、事务处理、性能优化等方面的知识,对于深入理解Android应用的数据存储机制具有很高的学习价值。

    Android中SQLite数据库查看工具

    SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库不一样,您不需要在系统中配置。 就像其他数据库,SQLite 引擎不是一个...

    Android实验报告Sqlite数据库操作.pdf

    Android SQLite 数据库操作报告 一、实验目的 Android 实验报告的主要目的是熟悉 Android 平台的文件操作、掌握 Android SQLite 数据库的设计和应用、熟悉 XML 和 JSON 文件的读取。通过本实验,用户可以掌握 ...

    android操作数据库Sqlite源代码

    以上是基于Android操作SQLite数据库的一些核心概念和源代码组织方式。实际开发中,还需要考虑数据同步、数据备份、数据加密等高级功能,以及性能优化,如批量插入、使用索引等。学习并理解这些知识点,将有助于你更...

    Android开发学习教程—Android使用SQLite数据库

    ### Android开发学习教程—深入解析Android使用SQLite数据库 #### SQLite数据库概述 SQLite是一款轻量级、高性能的嵌入式数据库,被广泛应用于各种资源受限的环境中,如移动设备。它支持标准的SQL语言,占用内存极...

    Android 数据库SQLite 详细介绍

    - SQLite是一个自包含的、无服务器的、零配置的、事务性的SQL数据库引擎,适合嵌入式环境,如Android。 - 它提供了一种灵活的方式来存储和检索数据,不需要额外的数据库服务器进程。 2. **Android与SQLite的结合*...

    android导入外部的数据库sqlite

    android应用,将外部的sqlite数据库导入到应用的私有空间中,源db文件置于assets目录下,如果源文件大小超过1M,使用Filesplit分割为不超过1M的小文件,那么就将所有分小文件置于assets目录下,本工程里已带...

    Android 数据库 SQlite 范例 SQLiteOpenHelper

    在Android开发中,SQLite是一个轻量级的数据库引擎,它被集成到Android系统中,用于存储应用程序的数据。SQLiteOpenHelper是Android SDK提供的一种管理SQLite数据库的工具类,它可以帮助我们完成数据库的创建、升级...

    android 的sqlite数据库加密实现

    在Android应用开发中,SQLite是一个常用的轻量级数据库,它为数据存储提供了便利。然而,随着数据安全性的日益重要,对SQLite数据库进行加密是必要的,以保护敏感信息免受未授权访问。本篇文章将深入探讨如何在...

    Android数据库SQLite基本操作工程

    在Android应用开发中,SQLite是一个重要的组成部分,它是一个轻量级的、开源的、嵌入式的SQL数据库引擎,被广泛用于存储和管理应用程序中的数据。SQLite具有小巧、快速、可靠的特点,非常适合移动设备上的本地数据...

    arcgis for android 读取加载sqlite数据库.rar

    SQLite是一个自包含、无服务器、零配置、事务性的SQL数据库引擎,无需额外的数据库管理器进程,直接嵌入到应用程序中。它支持多种数据类型,如INT、REAL、TEXT、BLOB,并提供SQL标准的大部分功能。 2. **ArcGIS ...

    基于android的个人日记本程序(Sqlite数据库).zip

    此外,为了保证数据的一致性和完整性,Android应用通常会在事务(Transaction)中执行一系列的数据库操作。这样,即使在操作过程中发生异常,也能确保数据不会处于不一致的状态。在日记本程序中,添加、编辑和删除...

    Android-在浏览器管理中Sqlite数据库

    SQLite数据库管理系统在Android设备上广泛使用,因为它高效、可靠且易于使用。本文将深入探讨如何在Android的浏览器环境中管理和操作SQLite数据库。 首先,理解SQLite数据库的基本概念至关重要。SQLite是一个嵌入式...

    Android使用SQLite数据库

    ### Android使用SQLite数据库知识点详解 #### 一、SQLite简介及特点 SQLite是一款广泛使用的嵌入式数据库管理系统,因其轻量级特性和强大的功能而在多个领域得到了广泛应用。它支持标准SQL查询语言,仅需少量内存...

    SQLite 数据库事务

    通过包裹一系列 SQL 操作在事务中,可以保证在异常情况下数据的正确性。 综上所述,SQLite 的事务机制为开发者提供了强大而灵活的数据管理工具,确保了数据的可靠性和一致性。理解和熟练运用 SQLite 事务是构建高...

    Android 绿豆通讯录【SQLite数据库】

    前情提要:Android 数据库(SQLite) 【简介、创建、使用(增删改查、事务、实战演练)、数据显示控件(ListView、Adapter、实战演练)】 https://blog.csdn.net/weixin_44949135/article/details/105955663  Android ...

Global site tag (gtag.js) - Google Analytics