一、SQLite数据库:

  在Android平台上,集成了一个嵌入式关系型数据库—SQLite,SQLite3支持 NULL、INTEGER、REAL(浮点数字)、TEXT(字符串文本)和BLOB(二进制对象)数据类型,虽然它支持的类型只有五种,但实际上sqlite3也接受varchar(n)、char(n)、decimal(p,s) 等数据类型,只不过在运算或保存时会转成对应的五种数据类型。 SQLite最大的特点是你可以把各种类型的数据保存到任何字段中,而不用关心字段声明的数据类型是什么。例如:可以在Integer类型的字段中存放字符串,或者在布尔型字段中存放浮点数,或者在字符型字段中存放日期型值。但有一种情况例外:定义为INTEGER PRIMARY KEY的字段只能存储64位整数, 当向这种字段保存除整数以外的数据时,将会产生错误。 另外, SQLite 在解析CREATE TABLE 语句时,会忽略 CREATE TABLE 语句中跟在字段名后面的数据类型信息,如下面语句会忽略 name字段的类型信息:

CREATE TABLE person (personid integer primary key autoincrement, name varchar(20))
SQLite可以解析大部分标准SQL语句,如:
查询语句:select * from 表名 where 条件子句 group by 分组字句 having ... order by 排序子句
如:   select * from person
select * from person order by id desc
select name from person group by name having count(*)>1
分页SQL与mysql类似,下面SQL语句获取5条记录,跳过前面3条记录
  select * from Account limit 5 offset 3 或者 select * from Account limit 3,5
插入语句:insert into 表名(字段列表) values(值列表)。如: insert into person(name, age) values(‘传智’,3)
更新语句:update 表名 set 字段名=值 where 条件子句。如:update person set name=‘传智‘ where id=10
删除语句:delete from 表名 where 条件子句。如:delete from person where id=10

二、SQLiteOpenHelper对数据库进行版本管理:

  为了实现对数据库版本进行管理,SQLiteOpenHelper类提供了两个重要的方法,分别是onCreate(SQLiteDatabase db)和onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion),前者用于初次使用软件时生成数据库表,后者用于升级软件时更新数据库表结构。当调用SQLiteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法获取用于操作数据库的SQLiteDatabase实例的时候,如果数据库不存在,Android系统会自动生成一个数据库,接着调用onCreate()方法,onCreate()方法在初次生成数据库时才会被调用,在onCreate()方法里可以生成数据库表结构及添加一些应用使用到的初始化数据。onUpgrade()方法在数据库的版本发生变化时会被调用,一般在软件升级时才需改变版本号,而数据库的版本是由程序员控制的,假设数据库现在的版本是1,由于业务的变更,修改了数据库表结构,这时候就需要升级软件,升级软件时希望更新用户手机里的数据库表结构,为了实现这一目的,可以把原来的数据库版本设置为2(有同学问设置为3行不行?当然可以,如果你愿意,设置为100也行),并且在onUpgrade()方法里面实现表结构的更新。当软件的版本升级次数比较多,这时在onUpgrade()方法里面可以根据原版号和目标版本号进行判断,然后作出相应的表结构及数据更新。

  getWritableDatabase()和getReadableDatabase()方法都可以获取一个用于操作数据库的SQLiteDatabase实例。但getWritableDatabase() 方法以读写方式打开数据库,一旦数据库的磁盘空间满了,数据库就只能读而不能写,倘若使用getWritableDatabase()打开数据库就会出错。getReadableDatabase()方法先以读写方式打开数据库,如果数据库的磁盘空间满了,就会打开失败,当打开失败后会继续尝试以只读方式打开数据库。

  第一次调用getWritableDatabase()或getReadableDatabase()方法后,SQLiteOpenHelper会缓存当前的SQLiteDatabase实例,SQLiteDatabase实例正常情况下会维持数据库的打开状态,所以在你不再需要SQLiteDatabase实例时,请及时调用close()方法释放资源。一旦SQLiteDatabase实例被缓存,多次调用getWritableDatabase()或getReadableDatabase()方法得到的都是同一实例。

public class DatabaseHelper extends SQLiteOpenHelper {
//类没有实例化,是不能用作父类构造器的参数,必须声明为静态
private static final String name = "android"; //数据库名称
private static final int version = 1; //数据库版本
public DatabaseHelper(Context context) {
//第三个参数CursorFactory指定在执行查询时获得一个游标实例的工厂类,设置为null,代表使用系统默认的工厂类
super(context, name, null, version);
}
@Override public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS person (personid integer primary key autoincrement, name varchar(20), age INTEGER)");
}
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS person");
onCreate(db);
//ALTER TABLE person ADD phone VARCHAR(12) NULL 往表中增加一列
}
}
//上面onUpgrade()方法在数据库版本每次发生变化时都会把用户手机上的数据库表删除,然后再重新创建。一般在实际项目中是不能这样做的,正确的做法是在更新数据库表结构时,
还要考虑用户存放于数据库中的数据不会丢失。

三、业务类及测试代码:

  操作有两种方法,一种是通过execSQL方法,另一种是通过rawQuery方法。前面是原生的sql语句,后面通过StringBuffer来拼接sql语句,最终的结果都是相同的。

  通过execSql实现业务类:

package com.example.service;

import java.util.ArrayList;
import java.util.List; import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import com.example.entity.Person; public class DBPersonService {
private DBOpenHelper dbOpenHelper; public DBPersonService(Context context) {
dbOpenHelper = new DBOpenHelper(context);
} /**
* 保存
* @param person
*/
public void save(Person person) {
// 调用getWritableDatabase向数据库写数据
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
db.execSQL("insert into person(name,age) values(?,?)", new Object[]{
person.getName(),person.getAge()});
}
/**
* 根据id删除
*/
public void delete(Integer id) {
// 调用getWritableDatabase向数据库写数据
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
db.execSQL("delete from person where id=?", new Object[]{id});
}
/**
* 更新
* @param person
*/
public void update(Person person) {
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
db.execSQL("update person set name=?,age=? where id=?", new Object[]{
person.getName(),person.getAge(),person.getId()
});
}
/**
* 根据id查找
* @param id
* @return
*/
public Person find(Integer id) {
// 调用getWritableDatabase向数据库写数据
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
Person person = null;
Cursor cursor = db.rawQuery("select * from person where id=?", new String[]{id.toString()});
if(cursor.moveToFirst()){
int personid = cursor.getInt(cursor.getColumnIndex("id"));
String name = cursor.getString(cursor.getColumnIndex("name"));
int age = cursor.getInt(cursor.getColumnIndex("age"));
person = new Person(personid, name, age);
} cursor.close();
return person;
}
/**
* 获取分页
* @param start 开始索引
* @param end 结束索引
* @return
*/
public List<Person> getScrollData(Integer start,Integer end) {
// 调用getWritableDatabase向数据库写数据
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
List<Person> persons = new ArrayList<Person>();
Cursor cursor = db.rawQuery("select * from person order by id asc limit ?,?",
new String[]{start.toString(),end.toString()});
while(cursor.moveToNext()){
int personid = cursor.getInt(cursor.getColumnIndex("id"));
String name = cursor.getString(cursor.getColumnIndex("name"));
int age = cursor.getInt(cursor.getColumnIndex("age"));
persons.add(new Person(personid, name, age));
} cursor.close();
return persons;
}
/**
* 获取总记录
* @return
*/
public long getCount(){
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("select count(*) from person", null);
cursor.moveToFirst();
long count = cursor.getLong(0);
cursor.close();
return count;
}
}

  游标介绍:

  Cursor是结果集游标,用于对结果集进行随机访问,如果大家熟悉jdbc, 其实Cursor与JDBC中的ResultSet作用很相似。使用moveToNext()方法可以将游标从当前行移动到下一
行,如果已经移过了结果集的最后一行,返回结果为false,否则为true。另外Cursor 还有常用的moveToPrevious()方法(用于将游标从当前行移动到上一行,如果已经移过了结果
集的第一行,返回值为false,否则为true )、moveToFirst()方法(用于将游标移动到结果集的第一行,如果结果集为空,返回值为false,否则为true )和moveToLast()方法(
用于将游标移动到结果集的最后一行,如果结果集为空,返回值为false,否则为true ) 。
public class DBOpenHelper extends SQLiteOpenHelper {

    private static String name="android.db";
private static int version=2;
public DBOpenHelper(Context context) {
//第三个参数CursorFactory指定在执行查询时得一个游标实例的工厂类,设置为null,代表使用系统默认的工厂类
super(context, name, null, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE person (id integer primary key autoincrement, name varchar(20))");
}
@Override
public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {
db.execSQL("ALTER TABLE person ADD age integer ");
} }

  通过rawQuery实现业务类:

package com.example.service;

import java.util.ArrayList;
import java.util.List; import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import com.example.entity.Person;
public class OtherDBPersonService {
private DBOpenHelper dbOpenHelper; public OtherDBPersonService(Context context) {
dbOpenHelper = new DBOpenHelper(context);
} /**
* 保存
* @param person
*/
public void save(Person person) {
// 调用getWritableDatabase向数据库写数据
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("name", person.getName());
cv.put("age", person.getAge());
//第二个参数:空值字段
//例如:将第二个参数设置为"name",表示cv里面没有name键(或无值),这时sql语句拼接出错,为了
//防止拼接出错,当没name键时,将name字段设置为NULL
//db.insert("person", "name", cv);
db.insert("person", null, cv);
}
/**
* 根据id删除
*/
public void delete(Integer id) {
// 调用getWritableDatabase向数据库写数据
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
db.delete("person", "id=?", new String[]{id.toString()});
}
/**
* 更新
* @param person
*/
public void update(Person person) {
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("name", person.getName());
cv.put("age", person.getAge());
db.update("person", cv, "id=?", new String[]{person.getId().toString()});
}
/**
* 根据id查找
* @param id
* @return
*/
public Person find(Integer id) {
// 调用getWritableDatabase向数据库写数据
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
Person person = null;
Cursor cursor = db.query("person", null, "id=?", new String[]{id.toString()}, null, null, null);
if(cursor.moveToFirst()){
int personid = cursor.getInt(cursor.getColumnIndex("id"));
String name = cursor.getString(cursor.getColumnIndex("name"));
int age = cursor.getInt(cursor.getColumnIndex("age"));
person = new Person(personid, name, age);
} cursor.close();
return person;
}
/**
* 获取分页
* @param start 开始索引
* @param end 结束索引
* @return
*/
public List<Person> getScrollData(Integer start,Integer end) {
// 调用getWritableDatabase向数据库写数据
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
List<Person> persons = new ArrayList<Person>();
Cursor cursor = db.query("person", null, null, null, null, null, null, start+","+end);
while(cursor.moveToNext()){
int personid = cursor.getInt(cursor.getColumnIndex("id"));
String name = cursor.getString(cursor.getColumnIndex("name"));
int age = cursor.getInt(cursor.getColumnIndex("age"));
persons.add(new Person(personid, name, age));
} cursor.close();
return persons;
}
/**
* 获取总记录
* @return
*/
public long getCount(){
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
Cursor cursor = db.query("person", new String[]{"count(*)"}, null, null, null, null, null);
cursor.moveToFirst();
long count = cursor.getLong(0);
cursor.close();
return count;
}
}

测试代码

package com.example.test;

import android.test.AndroidTestCase;
import android.util.Log; import com.example.entity.Person;
import com.example.service.DBOpenHelper;
import com.example.service.OtherDBPersonService; public class OtherDBPersonServiceTest extends AndroidTestCase {
private static final String TAG = "OtherOtherDBPersonServiceTest"; public void testCreateDB() {
DBOpenHelper helper = new DBOpenHelper(getContext());
helper.getWritableDatabase();
} public void testSave() {
OtherDBPersonService service = new OtherDBPersonService(getContext());
for (int i = 0; i < 50; i++) {
service.save(new Person(i, "tom" + i, i));
}
} public void testUpdate() {
OtherDBPersonService service = new OtherDBPersonService(getContext());
Person person = service.find(1);
Log.i(TAG, person.getAge().toString());
person.setAge(1);
service.update(person);
Log.i(TAG, service.find(1).getAge().toString());
} public void testDelete() {
OtherDBPersonService service = new OtherDBPersonService(getContext());
service.delete(15);
} public void testFind() {
OtherDBPersonService service = new OtherDBPersonService(getContext());
Log.i(TAG, service.find(10).toString());
} public void testGetScrollData() {
OtherDBPersonService service = new OtherDBPersonService(getContext());
for (Person peroson : service.getScrollData(0, 20)) {
Log.i(TAG, peroson.toString());
} } public void testCount() {
OtherDBPersonService service = new OtherDBPersonService(getContext());
Log.i(TAG, " 总记录: " + service.getCount());
}
}

四、测试结果:
  创建好数据库之后,可以通过SQLite Expert工具打开,创建的数据库位于当前应用的databases文件夹下。

  数据库版本控制,当版本改变时,就会执行onUpgrade方法。下面是版本改变时,给person表增加一个age字段。

五、事务管理:

/* 使用SQLiteDatabase的beginTransaction()方法可以开启一个事务,程序执行到endTransaction() 方法时会检查事务的标志是否为成功,如果程序执行到
  endTransaction()之前调用了setTransactionSuccessful() 方法设置事务的标志为成功则提交事务,如果没有调用setTransactionSuccessful() 方法则回滚事务。
  使用例子如下:SQLiteDatabase db = ....;
*/
db.beginTransaction();//开始事务
try {
db.execSQL("insert into person(name, age) values(?,?)", new Object[]{"tom", 4});
db.execSQL("update person set name=? where personid=?", new Object[]{"tom2", 1});
db.setTransactionSuccessful();//调用此方法会在执行到endTransaction() 时提交当前事务,如果不调用此方法会回滚事务
} finally {
db.endTransaction();//由事务的标志决定是提交事务,还是回滚事务
}
db.close();

Android学习笔记_9_SQLiteOpenHelper对象之数据库增删改查以及事务回滚操作的更多相关文章

  1. ASP.NET学习笔记(3)——用户增删改查(三层)

    说明(2017-10-6 11:21:58): 1. 十一放假在家也没写几行代码,本来还想着利用假期把asp.net看完,结果天天喝酒睡觉,回去的票也没买到,惨.. 2. 断断续续的把用户信息的页面写 ...

  2. C学习笔记-结构体与二进制文件增删改查

    使用结构体整理数据,然后利用二进制存储文件,这样存储的文件类似于数据库,可以实现文件的增删改查 定义结构体 struct student { unsigned int ID; char name[20 ...

  3. ASP.NET C# 连接 Oracle数据库增删改查,事务

    一.知识介绍 ①ASP.NET 使用的是MVC模式,开发工具Visual studio ,语言C# ②Oracle是比较重型的数据库,这里主要介绍连接数据库,对数据进行具体的使用 ③Visual St ...

  4. 【EF学习笔记04】----------EF简单增删改查

    第一步:创建上下文对象 using(var db = new Entities()) { //数据操作 } 新增 UserInfo user = new UserInfo() { UserName = ...

  5. MongoDB学习【三】—MongoDB数据库增删改查

    一.数据库的增删查 # 增加 use db # 有则切换,无则新 增 # 查看 show dbs # 查看所有数据库 db # 查看当前库 # 删除 db.dropDatabase() # 不会就用h ...

  6. C# 连接 Oracle数据库增删改查,事务

    一. 前情提要 一般.NET环境连接Oracle数据库,是通过 TNS/SQL.NET 配置文件,而 TNS 必须要 Oracle 客户端(如果连接的是服务器的数据库,本地还要装一个 client , ...

  7. mongo学习笔记(一):增删改查

    安装:我是按这篇来弄的 一.Insert 1.db.person.insert({"name":"jack","age":20}) 2.va ...

  8. ASP.NET学习笔记(2)——用户增删改查

    说明(2017-7-4 11:48:50): 1. index.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transition ...

  9. Android(java)学习笔记193:利用谷歌API对数据库增删改查(推荐使用)

    接下来我们通过项目案例来介绍:这个利用谷歌API对数据库增删改查 1.首先项目图: 2.这里的布局文件activity_main.xml: <LinearLayout xmlns:android ...

随机推荐

  1. 重入锁--ReentrantLock

    本部分主要参考<java并发编程艺术>一书相关内容,同时参考https://blog.csdn.net/zhilinboke/article/details/83104597,说的非常形象 ...

  2. TOJ 3744 Transportation Costs

    描述 Minya Konka decided to go to Fuzhou to participate in the ACM regional contest at their own expen ...

  3. SEH结构

    首先有几点问题 1.在后文中看到的PE的节中的配置信息表Load configuration是对SEH回调函数的注册,那么Exception Table是加载的什么信息. 2.什么时候走进系统异常,什 ...

  4. What is Network Address Translation?---reference

    http://whatismyipaddress.com/nat What is Network Address Translation? Network Address Translation (N ...

  5. 自己用 python 实现 base64 编码

    自己用 python 实现 base64 编码 base64 编码原理 二进制文件中包含有很多无法显示和打印的字符,二进制的数据一般以 ASCII 码形式(8 bit,即一个字节)存储,8 bit 可 ...

  6. backbone应用笔记

    由于公司手机端web的需要,最近开始用上backbone,之前觉得很难学,也一直没看到前端mvc具体是个啥,后来由于项目紧急,就抽空看了一遍underscore和backbone的源码,收获还是蛮大的 ...

  7. 利用pandas生成csv文件

    # -*- coding:UTF-8 -*- import json from collections import OrderedDict with open('dns_status.json',' ...

  8. C#博客记录二

    1.认识运算符 我认为其中 最重要的就是逻辑运算符,对于每个人来说学习web前端就是要有一个好的思维.能够更好的运用. 2.算数运算符 变量名++意味先输出,值后增加. ++变量名意味值先增加,后输出 ...

  9. WCF寄宿在C#控制台,并用命令行启动

    公司运用wcf比较多,所以自己研究一下寄宿做个笔记,wcf寄宿在控制台有两种方式 第一种,直接在控制台程序内添加wcf服务. 第二种分别添加控制台程序和wcf服务应用程序,前者引用后者,并在app.c ...

  10. XML入门介绍(什么是XML及XML格式)

    什么是 XML? XML 指可扩展标记语言(EXtensible Markup Language). XML 是一种很像HTML的标记语言. XML 的设计宗旨是传输数据,而不是显示数据. XML 标 ...