Android:SQLiteOpenHelper类(SQLlite数据库操作)详细解析
前言
- SQLite数据库操作在Android开发中非常常用
- 今天我将带大家全面了解关于SQLite数据库的操作(增、删、查、改)
目录
1. SQLite数据库介绍
- SQLite是Android内置的一个小型、关系型、属于文本型的数据库。 Android提供了对 SQLite数据库的完全支持,应用程序中的任何类都可以通过名称来访问任何的数据库,但是应用程序之外的就不能访问。
- Android中,通过SQLiteOpenHelper类来实现对SQLite数据库的操作。
2. SQLiteOpenHelper类介绍
- 定义:SQLiteOpenHelper是一个辅助类
- 作用:管理数据库(创建、增、修、删) & 版本的控制。
- 使用过程:通过创建子类继承SQLiteOpenHelper类,实现它的一些方法来对数据库进行操作。 在实际开发中,为了能够更好的管理和维护数据库,我们会封装一个继承自SQLiteOpenHelper类的数据库操作类,然后以这个类为基础,再封装我们的业务逻辑方法。
- SQLiteOpenHelper类的数据库操作方法介绍
方法名 |
作用 |
备注 |
---|---|---|
onCreate() |
创建数据库 |
创建数据库时自动调用 |
onUpgrade() |
升级数据库 |
|
close() |
关闭所有打开的数据库对象 |
|
execSQL() |
可进行增删改操作, 不能进行查询操作 |
|
query()、rawQuery() |
查询数据库 |
|
insert() |
插入数据 |
|
delete() |
删除数据 |
|
getWritableDatabase() |
创建或打开可以读/写的数据库 |
通过返回的SQLiteDatabase对象对数据库进行操作 |
getReadableDatabase() |
创建或打开可读的数据库 |
同上 |
3. 常见数据库使用
数据库操作无外乎:“增删查改”:
- 对于“增、删、改(更新)”这类对表内容变换的操作,需先调用getWritableDatabase()获得一个可写数据库对象,在执行的时候调用通用的execSQL(String sql)或或对应的操作API方法:insert()、delete()、update()
- 对“查”,需要调用getReadableDatabase()获得一个可读的数据库对象,然后使用query()或rawQuery()方法 查询数据库不能使用execSQL方法
下面我将一一介绍。
3.1 创建数据库
- 涉及的方法有onCreate()、getWritableDatabase()、getReadableDatabase()
- 具体代码如下: 假设DatabaseHelper类是SQLiteOpenHelper的子类
DatabaseHelper.java
//第一次创建数据库的时候回调该方法 //当使用getReadableDatabase()方法获取数据库实例的时候, 如果数据库不存在, 就会调用这个方法; //作用:创建数据库表:将创建数据库表的 execSQL()方法 和 初始化表数据的一些 insert()方法写在里面; @Override public void onCreate(SQLiteDatabase db) { //SQLite数据创建支持的数据类型: 整型数据,字符串类型,日期类型,二进制的数据类型 //创建了一个名为person的表 String sql = "create table person(id integer primary key autoincrement,name varchar(64),address varchar(64))"; //execSQL用于执行SQL语句 //完成数据库的创建 db.execSQL(sql); //数据库实际上是没有被创建或者打开的,直到getWritableDatabase() 或者 getReadableDatabase() 方法中的一个被调用时才会进行创建或者打开 //见下代码
*MainActivity.java*
// 创建DatabaseHelper对象 // 只执行这句话是不会创建或打开连接的 SQLiteOpenHelper dbHelper = new DatabaseHelper(SQLiteActivity.this, "test_carson"); // 调用getReadableDatabase()或getWritableDatabase()才算真正创建或打开数据库 SQLiteDatabase sqliteDatabase = dbHelper.getReadableDatabase(); //SQLiteDatabase sqliteDatabase = dbHelper.getWritableDatabase() ;
3.2 插入数据
- 步骤:创建并打开数据库(可读/写)、插入数据
- 涉及方法:getWritableDatabase()、insert() insert()也可以使用excelSQL()代替
- 具体代码如下:
//1. 创建并打开数据库 // 创建DatabaseHelper对象(记得传入最新版本的数据库) // 只执行这句话是不会创建或打开连接的 //注意,一定要传入最新的数据库版本号 SQLiteOpenHelper dbHelper = new DatabaseHelper(SQLiteActivity.this, "test_carson",2); // 调用getWritableDatabase()方法创建或打开一个可以读的数据库 //通过返回的SQLiteDatabase对象对数据库进行操作 SQLiteDatabase sqliteDatabase = dbHelper.getWritableDatabase(); //2. 创建并打开数据库 // 创建ContentValues对象 ContentValues values = new ContentValues(); // 向该对象中插入键值对 values.put("id", 1); values.put("name", "yangyz"); //其中,key代表列名,value代表该列要插入的值 //注:ContentValues内部实现就是HashMap,但是两者还是有差别的 //ContenValues Key只能是String类型,Value只能存储基本类型数据,不能存储对象 // 调用insert()方法将数据插入到数据库当中 sqliteDatabase.insert("user", null, values); // 第一个参数:要操作的表名称 // 第二个参数:SQl不允许一个空列,如果ContentValues是空的,那么这一列被明确的指明为NULL值 // 第三个参数:ContentValues对象 ////db.execSQL("insert into user (id,name) values (1,'张三')") 也可以 }
3.3 修改数据(升级数据库)
- 涉及的方法有onUpgrade()、getWritableDatabase()、update()
- 具体代码如下:
DatabaseHelper.java
//数据库版本号 private static final int DATABASE_VERSION = 1; //作用:更新数据库表结构 //调用时机:数据库版本发生变化的时候回调(取决于数据库版本) // 创建SQLiteOpenHelper子类对象的时候,必须传入一个version参数 //该参数就是当前数据库版本, 只要这个版本高于之前的版本, 就会触发这个onUpgrade()方法,如下面代码 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { //使用SQL的ALTER语句 String sql = "alter table person add sex varchar(8)"; db.execSQL(sql); } //参数说明: // db : 数据库 //oldVersion : 旧版本数据库 //newVersion : 新版本数据库 //注意:这里的删除等操作必须要保证新的版本必须要比旧版本的版本号要大才行。[即 Version 2.0 > Version 1.0 ] 所以这边我们不需要对其进行操作。
MainActivity.java
// 创建一个DatabaseHelper对象 // 创建SQLiteOpenHelper子类对象的时候,必须传入一个version参数 //该参数就是当前数据库版本, 只要这个版本高于之前的版本, 就会触发这个onUpgrade()方法,如下面代码 ////注意,一定要传入最新的数据库版本号 // 传入版本号为2,大于旧版本(1),所以会调用onUpgrade()升级数据库 DatabaseHelper dbHelper = new DatabaseHelper(SQLiteActivity.this, "test_carson", 2); // 调用getWritableDatabase()得到一个可写的SQLiteDatabase对象 SQLiteDatabase sqliteDatabase = dbHelper.getWritableDatabase(); // 创建一个ContentValues对象 ContentValues values = new ContentValues(); values.put("name", "zhangsan"); // 调用update方法修改数据库 sqliteDatabase.update("user", values, "id=?", new String[] { "1" }); // 第一个参数String:表名 // 第二个参数ContentValues:ContentValues对象(需要修改的) // 第三个参数String:WHERE表达式,where选择语句, 选择那些行进行数据的更新, 如果该参数为 null, 就会修改所有行;?号是占位符 // 第四个参数String[]:where选择语句的参数, 逐个替换 whereClause 中的占位符;
3.4 删除数据
- 步骤:创建并打开数据库(可读/写)、删除数据
- 涉及方法:getWritableDatabase()、delete() delete()也可以使用excelSQL()代替
- 具体代码如下:
//1. 创建并打开数据库 // 创建DatabaseHelper对象 // 只执行这句话是不会创建或打开连接的 ////注意,一定要传入最新的数据库版本号 SQLiteOpenHelper dbHelper = new DatabaseHelper(SQLiteActivity.this, "test_carson",2); // 调用getWritableDatabase()方法创建或打开一个可以读的数据库 //通过返回的SQLiteDatabase对象对数据库进行操作 SQLiteDatabase sqliteDatabase = dbHelper.getWritableDatabase(); //2. 删除数据 //调用delete方法进行删除操作 sqliteDatabase.delete("user", "id=?", new String[]{"1"}); //第一个参数String:需要操作的表名 //第二个参数String:where选择语句, 选择哪些行要被删除, 如果为null, 就删除所有行; //第三个参数String[]: where语句的参数, 逐个替换where语句中的 "?" 占位符;
3.5 查询数据
- 步骤:创建并打开数据库(可读)、查询数据
- 涉及方法:getReadableDatabase()、query() 或 rawQuery(),介绍如下:
//第一种最为简单 //将所有的SQL语句都组织到一个字符串中,使用占位符代替实际参数(selectionArgs) db.rawQuery(String sql, String[] selectionArgs); db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy); db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit); db.query(String distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit); //参数说明 //table:要操作的表明 //columns:查询的列所有名称集 //selection:WHERE之后的条件语句,可以使用占位符 //groupBy:指定分组的列名 //having指定分组条件,配合groupBy使用 //orderBy指定排序的列名 //limit指定分页参数 //distinct可以指定“true”或“false”表示要不要过滤重复值 //所有方法将返回一个Cursor对象,代表数据集的游标 //Cursor对象常用方法如下: c.move(int offset); //以当前位置为参考,移动到指定行 c.moveToFirst(); //移动到第一行 c.moveToLast(); //移动到最后一行 c.moveToPosition(int position); //移动到指定行 c.moveToPrevious(); //移动到前一行 c.moveToNext(); //移动到下一行 c.isFirst(); //是否指向第一条 c.isLast(); //是否指向最后一条 c.isBeforeFirst(); //是否指向第一条之前 c.isAfterLast(); //是否指向最后一条之后 c.isNull(int columnIndex); //指定列是否为空(列基数为0) c.isClosed(); //游标是否已关闭 c.getCount(); //总数据项数 c.getPosition(); //返回当前游标所指向的行数 c.getColumnIndex(String columnName);//返回某列名对应的列索引值 c.getString(int columnIndex); //返回当前行指定列的值
- 具体代码如下:
//1. 创建并打开数据库 // 创建DatabaseHelper对象 // 只执行这句话是不会创建或打开连接的 ////注意,一定要传入最新的数据库版本号 SQLiteOpenHelper dbHelper = new DatabaseHelper(SQLiteActivity.this, "test_carson",2); // 调用getReadableDatabase()方法创建或打开一个可以读的数据库 //通过返回的SQLiteDatabase对象对数据库进行操作 SQLiteDatabase sqliteDatabase = dbHelper.getReadableDatabase(); //2. 查询数据 // 调用SQLiteDatabase对象的query方法进行查询 // 返回一个Cursor对象:由数据库查询返回的结果集对象 Cursor cursor = sqliteDatabase.query("user", new String[] { "id", "name" }, "id=?", new String[] { "1" }, null, null, null); // 第一个参数String:表名 // 第二个参数String[]:要查询的列名 // 第三个参数String:查询条件 // 第四个参数String[]:查询条件的参数 // 第五个参数String:对查询的结果进行分组 // 第六个参数String:对分组的结果进行限制 // 第七个参数String:对查询的结果进行排序 // 将光标移动到下一行,从而判断该结果集是否还有下一条数据 //如果有则返回true,没有则返回false while (cursor.moveToNext()) { id = cursor.getString(cursor.getColumnIndex("id")); name = cursor.getString(cursor.getColumnIndex("name")); } //也可将Cursor中的数据转为 ArrayList<Map<String, String>> 类型数据 private ArrayList<Map<String, String>> cursor2list(Cursor cursor) { ArrayList<Map<String, String>> list = new ArrayList<Map<String,String>>(); //遍历Cursor while(cursor.moveToNext()){ Map<String, String> map = new HashMap<String, String>(); map.put("tittle", cursor.getString(1)); map.put("content", cursor.getString(2)); list.add(map); } return list; }
3.6 关闭数据库
当我们完成了对数据库的操作后,记得调用SQLiteDatabase的close()方法释放数据库连接,否则容易出现SQLiteException。
SQLiteOpenHelper dbHelper = new DatabaseHelper(SQLiteActivity.this, "test_carson"); // 调用getReadableDatabase()方法创建或打开一个可以读的数据库 //通过返回的SQLiteDatabase对象对数据库进行操作 SQLiteDatabase sqliteDatabase = dbHelper.getReadableDatabase(); //关闭当前数据库 sqliteDatabase.close();
3.7 删除数据库
SQLiteOpenHelper dbHelper = new DatabaseHelper(SQLiteActivity.this, "test_carson"); // 调用getReadableDatabase()方法创建或打开一个可以读的数据库 //通过返回的SQLiteDatabase对象对数据库进行操作 SQLiteDatabase sqliteDatabase = dbHelper.getReadableDatabase(); //删除名为test.db数据库 deleteDatabase("test.db");
特别注意
其实对于上述所有的数据库操作(除了“查询”),我们都可以使用下列方法代替:
db.executeSQL(String sql); db.executeSQL(String sql, Object[] bindArgs); //sql语句中使用占位符,然后第二个参数是实际的参数集
个人建议都使用SQL语句,因为:
- SQL语句较为通用;
- 使用insert()、delete()、query()方法具备多个参数,使用复杂
4. 实例Demo
- Demo描述:创建数据库并对数据库进行操作(增、删、查、改)
- 实现步骤:
- 实现子类继承SQLiteOpenHelper类(复写onCreat()、onUpgrade())
- 在MainActivity里实现需要进行的数据库操作(增、删、查、改)
4.1 具体代码如下:
建议先下载Demo再进行阅读:Carson的Github:DataBase_Demo
步骤1:实现子类继承SQLiteOpenHelper类(复写onCreat()、onUpgrade())
MySQLiteOpenHelper.java
package scut.carson_ho.database_demo; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; /** * Created by Carson_Ho on 16/11/18. */ public class MySQLiteOpenHelper extends SQLiteOpenHelper { //数据库版本号 private static Integer Version = 1; //在SQLiteOpenHelper的子类当中,必须有该构造函数 public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { //必须通过super调用父类当中的构造函数 super(context, name, factory, version); } //参数说明 //context:上下文对象 //name:数据库名称 //param:factory //version:当前数据库的版本,值必须是整数并且是递增的状态 public MySQLiteOpenHelper(Context context,String name,int version) { this(context,name,null,version); } public MySQLiteOpenHelper(Context context,String name) { this(context, name, Version); } //当数据库创建的时候被调用 @Override public void onCreate(SQLiteDatabase db) { System.out.println("创建数据库和表"); //创建了数据库并创建一个叫records的表 //SQLite数据创建支持的数据类型: 整型数据,字符串类型,日期类型,二进制的数据类型 String sql = "create table user(id int primary key,name varchar(200))"; //execSQL用于执行SQL语句 //完成数据库的创建 db.execSQL(sql); //数据库实际上是没有被创建或者打开的,直到getWritableDatabase() 或者 getReadableDatabase() 方法中的一个被调用时才会进行创建或者打开 } //数据库升级时调用 //如果DATABASE_VERSION值被改为2,系统发现现有数据库版本不同,即会调用onUpgrade()方法 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { System.out.println("更新数据库版本为:"+newVersion); } }
步骤2:在MainActivity里实现需要进行的数据库操作(增、删、查、改)
MainActivity.java
package scut.carson_ho.database_demo; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button instablish; private Button insert; private Button upgrade; private Button modify; private Button delete; private Button query; private Button delete_database; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //绑定按钮 instablish = (Button) findViewById(R.id.instablish); insert = (Button) findViewById(R.id.insert); upgrade = (Button) findViewById(R.id.upgrade); modify = (Button) findViewById(R.id.modify); delete = (Button) findViewById(R.id.delete); query = (Button) findViewById(R.id.query); delete_database = (Button) findViewById(R.id.delete_database); //设置监听器 instablish.setOnClickListener(this); insert.setOnClickListener(this); upgrade.setOnClickListener(this); modify.setOnClickListener(this); delete.setOnClickListener(this); query.setOnClickListener(this); delete_database.setOnClickListener(this); } //设置每个按钮对数据库的操作进行控制 @Override public void onClick(View v) { switch (v.getId()) { //点击创建数据库库 case R.id.instablish: // 创建SQLiteOpenHelper子类对象 MySQLiteOpenHelper dbHelper = new MySQLiteOpenHelper(this,"test_carson"); //数据库实际上是没有被创建或者打开的,直到getWritableDatabase() 或者 getReadableDatabase() 方法中的一个被调用时才会进行创建或者打开 SQLiteDatabase sqliteDatabase = dbHelper.getWritableDatabase(); // SQLiteDatabase sqliteDatabase = dbHelper.getReadbleDatabase(); break; //点击更新数据 case R.id.upgrade: // 创建SQLiteOpenHelper子类对象 MySQLiteOpenHelper dbHelper_upgrade = new MySQLiteOpenHelper(this,"test_carson",2); // 调用getWritableDatabase()方法创建或打开一个可以读的数据库 SQLiteDatabase sqliteDatabase_upgrade = dbHelper_upgrade.getWritableDatabase(); // SQLiteDatabase sqliteDatabase = dbHelper.getReadbleDatabase(); break; //点击插入数据到数据库 case R.id.insert: System.out.println("插入数据"); // 创建SQLiteOpenHelper子类对象 ////注意,一定要传入最新的数据库版本号 MySQLiteOpenHelper dbHelper1 = new MySQLiteOpenHelper(this,"test_carson",2); // 调用getWritableDatabase()方法创建或打开一个可以读的数据库 SQLiteDatabase sqliteDatabase1 = dbHelper1.getWritableDatabase(); // 创建ContentValues对象 ContentValues values1 = new ContentValues(); // 向该对象中插入键值对 values1.put("id", 1); values1.put("name", "carson"); // 调用insert()方法将数据插入到数据库当中 sqliteDatabase1.insert("user", null, values1); // sqliteDatabase.execSQL("insert into user (id,name) values (1,'carson')"); //关闭数据库 sqliteDatabase1.close(); break; //点击查询数据库 case R.id.query: System.out.println("查询数据"); // 创建DatabaseHelper对象 MySQLiteOpenHelper dbHelper4 = new MySQLiteOpenHelper(MainActivity.this,"test_carson",2); // 调用getWritableDatabase()方法创建或打开一个可以读的数据库 SQLiteDatabase sqliteDatabase4 = dbHelper4.getReadableDatabase(); // 调用SQLiteDatabase对象的query方法进行查询 // 返回一个Cursor对象:由数据库查询返回的结果集对象 Cursor cursor = sqliteDatabase4.query("user", new String[] { "id", "name" }, "id=?", new String[] { "1" }, null, null, null); String id = null; String name = null; //将光标移动到下一行,从而判断该结果集是否还有下一条数据 //如果有则返回true,没有则返回false while (cursor.moveToNext()) { id = cursor.getString(cursor.getColumnIndex("id")); name = cursor.getString(cursor.getColumnIndex("name")); //输出查询结果 System.out.println("查询到的数据是:"+"id: "+id+" "+"name: "+name); } //关闭数据库 sqliteDatabase4.close(); break; //点击修改数据 case R.id.modify: System.out.println("修改数据"); // 创建一个DatabaseHelper对象 // 将数据库的版本升级为2 // 传入版本号为2,大于旧版本(1),所以会调用onUpgrade()升级数据库 MySQLiteOpenHelper dbHelper2 = new MySQLiteOpenHelper(MainActivity.this,"test_carson", 2); // 调用getWritableDatabase()得到一个可写的SQLiteDatabase对象 SQLiteDatabase sqliteDatabase2 = dbHelper2.getWritableDatabase(); // 创建一个ContentValues对象 ContentValues values2 = new ContentValues(); values2.put("name", "zhangsan"); // 调用update方法修改数据库 sqliteDatabase2.update("user", values2, "id=?", new String[]{"1"}); //关闭数据库 sqliteDatabase2.close(); break; //点击删除数据 case R.id.delete: System.out.println("删除数据"); // 创建DatabaseHelper对象 MySQLiteOpenHelper dbHelper3 = new MySQLiteOpenHelper(MainActivity.this,"test_carson",2); // 调用getWritableDatabase()方法创建或打开一个可以读的数据库 SQLiteDatabase sqliteDatabase3 = dbHelper3.getWritableDatabase(); //删除数据 sqliteDatabase3.delete("user", "id=?", new String[]{"1"}); //关闭数据库 sqliteDatabase3.close(); break; //点击删除数据库 case R.id.delete_database: System.out.println("删除数据库"); MySQLiteOpenHelper dbHelper5 = new MySQLiteOpenHelper(MainActivity.this, "test_carson",2); // 调用getReadableDatabase()方法创建或打开一个可以读的数据库 SQLiteDatabase sqliteDatabase5 = dbHelper5.getReadableDatabase(); //删除名为test.db数据库 deleteDatabase("test_carson"); break; default: break; } } }
步骤3:在主布局文件设置按钮控制数据库的操作 activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="scut.carson_ho.database_demo.MainActivity"> <Button android:id="@+id/instablish" android:layout_centerHorizontal="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="创建数据库"/> <Button android:id="@+id/upgrade" android:layout_below="@+id/instablish" android:layout_centerHorizontal="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="更新数据库"/> <Button android:id="@+id/insert" android:layout_below="@+id/upgrade" android:layout_centerHorizontal="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="插入数据"/> <Button android:id="@+id/modify" android:layout_centerHorizontal="true" android:layout_below="@+id/insert" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="修改数据"/> <Button android:id="@+id/query" android:layout_centerHorizontal="true" android:layout_below="@+id/modify" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="查询数据"/> <Button android:id="@+id/delete" android:layout_centerHorizontal="true" android:layout_below="@+id/query" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="删除数据"/> <Button android:id="@+id/delete_database" android:layout_centerHorizontal="true" android:layout_below="@+id/delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="删除数据库"/> </RelativeLayout>
4.2 测试结果
- 界面显示
- 按顺序点击:创建 - 更新 - 插入 - 查询 - 修改 - 查询 - 删除数据
4.3 Demo下载地址
Carson的Github地址:DataBase_Demo
5. 总结
- 通过阅读本文,你将全面了解Android SQLite数据库中的所有操作、
- 接下来会介绍继续介绍Android开发中的相关知识,有兴趣可以继续关注Carson_Ho的安卓开发笔记