Android数据库开发——SQLite

简介: 上篇博客提到过SQLite,它是嵌入式数据库,由于其轻巧但功能强大,被广泛的用于嵌入式设备当中。

上篇博客提到过SQLite,它是嵌入式数据库,由于其轻巧但功能强大,被广泛的用于嵌入式设备当中。后来在智能手机、平板流行之后,它作为文件型数据库,几乎成为了智能设备单机数据库的必选,可以随着安卓app打包到apk文件当中。

SQLite的官方网站是http://www.sqlite.org/,可以任意下载,上面也有详尽的文档可以参考,这篇博客重点关注SQLite在Android开发中如何使用。

在Android开发中,推荐建立一个类继承自SQLiteOpenHelper来创建数据库操作类,比如:

public class DBHelper extends SQLiteOpenHelper {

	private static final String database = "test.db";
	private static final Integer version = 1;

	public DBHelper(Context context) {

		// 构造函数初始化各成员变量
		super(context, database, null, version);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {

		// 当通过SQLiteOpenHelper的子类获取数据库连接时,如果数据库不存在,则调用onCreate方法来创建数据库
		String sql = "create table Score(id integer primary key autoincrement,name varchar(20),point integer)";
		db.execSQL(sql);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		// 当传入的实例的数据库版本号高于之前的版本号时,系统会自动调用onUpgrade方法更新数据库
		// 更新数据库的操作:备份数据库表数据,重新创建或修改表、约束等,然后将原来的数据导入到新建的表中。

	}
}
上面的代码有3点需要注意:

1、构造函数(方法)中指定了数据库的名称和版本号

它会默认的在data/data/包名/databases/目录下创建这个数据库,当然你也可以指定数据库文件存在的路径;版本号设置为1,如果你要想升级,可以在构造方法的参数中加上version,以便初始化。


2、onCreate是在数据库文件没有创建的时候执行,如果有了的话则不执行

3、onUpgrade是在新的指定版本号高于旧的指定版本号的时候执行,一般在数据库升级的时候需要操作

然后我们建一个具体的数据库操作类:

/**
 * 成绩操作类
 * 
 * @author guwei
 * 
 */
public class ScoreOp {

	// 插入一条成绩记录
	public long insert(SQLiteDatabase db, String name, Integer point) {
		try {
			db.beginTransaction();
			ContentValues values = new ContentValues();
			values.put("name", name);
			values.put("point", point);
			long result = db.insert("Score", null, values);
			if (result != -1) {
				db.setTransactionSuccessful();
			}
			return result;
		} finally {
			db.endTransaction();
		}
	}

	// 修改一条成绩记录
	public int update(SQLiteDatabase db, String name, Integer point) {
		try {
			db.beginTransaction();
			ContentValues values = new ContentValues();
			values.put("name", name);
			values.put("point", point);
			int result = db.update("Score", values, "name = ?",
					new String[] { name });
			db.setTransactionSuccessful();
			return result;
		} finally {
			db.endTransaction();
		}
	}

	// 删除一条成绩记录
	public long delete(SQLiteDatabase db, String name) {
		try {
			db.beginTransaction();
			int result = db.delete("Score", "name = ?", new String[] { name });
			db.setTransactionSuccessful();
			return result;
		} finally {
			db.endTransaction();
		}
	}

	// 查询根据name正向排序的前10条总分大于指定分数的人员信息
	public Cursor query(SQLiteDatabase db, Integer point) {
		return db.query("Score",
				new String[] { "name", "sum(point) as points" }, null, null,
				"name", "sum(point)>=" + point, "name asc", "0,10");
	}

	// 更灵活的查询,SQL任意拼接
	public Cursor query(SQLiteDatabase db, String sql, String[] selectionArgs) {
		return db.rawQuery(sql, selectionArgs);
	}
}
这上面封装了CRUD操作,而且都是带事务的(执行多条SQL时需要),值得关注的是最后的两个query方法。

第一个query是指定了一个复杂sql查询语句的情况。

按照顺序,参数的含义如下:

1)、table The table name to compile the query against.   

指定的查询的表名

2)、columns A list of which columns to return. Passing null will return all columns, which is discouraged to prevent reading data from storage that isn't going to be used.

返回的查询列表的列名

3)、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.

where条件,不包括where关键字

4)、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.

where条件指定的参数值

5)、groupBy A filter declaring how to group rows, formatted as an SQL GROUP BY clause (excluding the GROUP BY itself). Passing null will cause the rows to not be grouped.

group by分组后面跟着的列名

6)、having A filter declare which row groups to include in the cursor, if row grouping is being used, formatted as an SQL HAVING clause (excluding the HAVING itself). Passing null will cause all row groups to be included, and is required when row grouping is not being used.
having 后面紧跟着的在分组基础上进一步筛选的内容

7)、orderBy How to order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself). Passing null will use the default sort order, which may be unordered.

order by后面根据某字段排序

8)、limit Limits the number of rows returned by the query, formatted as LIMIT clause. Passing null denotes no LIMIT clause.
limit关键字,分页查询时使用

实际上上面对应的这8个参数,就是对应如下SQL查询语句各关键字后面的内容,其原理就是通过指定参数拼接如下SQL语句。

这里顺便提一下,SQLite Expert是非常好用的管理SQLite数据库的工具,可以在http://www.sqliteexpert.com/下载到,也可以直接搜索下载相应破解版本。

回到第二个query方法,参数很简单,只有一个sql语句以及一个string数组(提供sql语句参数的值)。这个方法的意义就在于它很灵活,可以直接把能够执行的sql扔进去执行,而且是参数化的,是第一种查询方法很有力的补充。

好,最后我们就可以写测试代码来验证了。界面很简单,直接放置一个按钮即可。

public class SQLiteActivity extends Activity {  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_sqlite);  
  
        Button btn = (Button) findViewById(R.id.btn);  
        btn.setOnClickListener(new View.OnClickListener() {  
  
            @Override  
            public void onClick(View v) {  
                DBHelper dbHelper = new DBHelper(SQLiteActivity.this);  
                  
                //获得一个可写数据库操作对象  
                SQLiteDatabase wdb = dbHelper.getWritableDatabase();  
                  
                //添加纪录  
                ScoreOp scoreOp = new ScoreOp();  
                scoreOp.insert(wdb, "zhang3", 98);  
                scoreOp.insert(wdb, "zhang3", 94);  
  
                scoreOp.insert(wdb, "li4", 92);  
                scoreOp.insert(wdb, "wang5", 89);  
                scoreOp.insert(wdb, "wang5", 82);  
  
                //修改记录  
                scoreOp.update(wdb, "li4", 90);  
  
                //删除记录  
                scoreOp.delete(wdb, "li4");  
  
                //获得一个可读数据库操作对象  
                SQLiteDatabase rdb = dbHelper.getReadableDatabase();  
                  
                // 1.可以调用系统提供的query方法,以指定参数的形式返回Cursor对象  
                // Cursor cursor = scoreOp.query(rdb, 192);  
  
                // 2.可以直接执行SQL查询语句  
                Cursor cursor = scoreOp  
                        .query(rdb,  
                                "select name,sum(point) as points from Score group by name having sum(point)>=192 order by name asc limit ?,?",  
                                new String[] { "0", "10" });  
                while (cursor.moveToNext()) {  
                    String name = cursor.getString(cursor  
                            .getColumnIndex("name"));  
                    Integer points = cursor.getInt(cursor  
                            .getColumnIndex("points"));  
  
                    Toast.makeText(SQLiteActivity.this,  
                            "姓名:" + name + ";总分:" + points, Toast.LENGTH_SHORT)  
                            .show();  
                }  
                cursor.close();  
            }  
        });  
  
    }  
  
}  


点击按钮执行之后就可以弹出符合条件的数据。如果不放心,可以切换到DDMS界面,选择File Explorer选项卡,找到路径下的我们创建的test.db文件,Pull(拉取)到电脑磁盘上,用SQLite Expert等工具打开验证。




目录
相关文章
|
2天前
|
编解码 Java Android开发
通义灵码:在安卓开发中提升工作效率的真实应用案例
本文介绍了通义灵码在安卓开发中的应用。作为一名97年的聋人开发者,我在2024年Google Gemma竞赛中获得了冠军,拿下了很多项目竞赛奖励,通义灵码成为我的得力助手。文章详细展示了如何安装通义灵码插件,并通过多个实例说明其在适配国际语言、多种分辨率、业务逻辑开发和编程语言转换等方面的应用,显著提高了开发效率和准确性。
|
1天前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
11 5
|
3天前
|
存储 IDE 开发工具
探索Android开发之旅:从新手到专家
【10月更文挑战第26天】在这篇文章中,我们将一起踏上一段激动人心的旅程,探索如何在Android平台上从零开始,最终成为一名熟练的开发者。通过简单易懂的语言和实际代码示例,本文将引导你了解Android开发的基础知识、关键概念以及如何实现一个基本的应用程序。无论你是编程新手还是希望扩展你的技术栈,这篇文章都将为你提供价值和启发。让我们开始吧!
|
7天前
|
存储 SQL 数据库
数据库知识:了解SQLite或其他移动端数据库的使用
【10月更文挑战第22天】本文介绍了SQLite在移动应用开发中的应用,包括其优势、如何在Android中集成SQLite、基本的数据库操作(增删改查)、并发访问和事务处理等。通过示例代码,帮助开发者更好地理解和使用SQLite。此外,还提到了其他移动端数据库的选择。
18 8
|
3天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
11 2
|
3天前
|
监控 Java 数据库连接
在Java开发中,数据库连接管理是关键问题之一
在Java开发中,数据库连接管理是关键问题之一。本文介绍了连接池技术如何通过预创建和管理数据库连接,提高数据库操作的性能和稳定性,减少资源消耗,并简化连接管理。通过示例代码展示了HikariCP连接池的实际应用。
9 1
|
9天前
|
Java API Android开发
安卓应用程序开发的新手指南:从零开始构建你的第一个应用
【10月更文挑战第20天】在这个数字技术不断进步的时代,掌握移动应用开发技能无疑打开了一扇通往创新世界的大门。对于初学者来说,了解并学习如何从无到有构建一个安卓应用是至关重要的第一步。本文将为你提供一份详尽的入门指南,帮助你理解安卓开发的基础知识,并通过实际示例引导你完成第一个简单的应用项目。无论你是编程新手还是希望扩展你的技能集,这份指南都将是你宝贵的资源。
33 5
|
7天前
|
设计模式 IDE Java
探索安卓开发:从新手到专家的旅程
【10月更文挑战第22天】 在数字时代的浪潮中,移动应用开发如同一座金矿,吸引着无数探险者。本文将作为你的指南针,指引你进入安卓开发的广阔天地。我们将一起揭开安卓平台的神秘面纱,从搭建开发环境到掌握核心概念,再到深入理解安卓架构。无论你是初涉编程的新手,还是渴望进阶的开发者,这段旅程都将为你带来宝贵的知识和经验的财富。让我们开始吧!
|
12天前
|
SQL JavaScript 关系型数据库
node博客小项目:接口开发、连接mysql数据库
【10月更文挑战第14天】node博客小项目:接口开发、连接mysql数据库
|
16天前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
62 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库