数据库存储
引言
对于大数量结构化数据的存取,采用文件的方式操作复杂,效率低下,因此Android系统引人了轻量级嵌人式关系数据库SQLite,支持SQL语言,可以方便地实现数据的增、删、改、查等操作。
SOLite 介绍
Android 系统集成了SOLite数据库,任何应用都可以使用它。默认情况下,SQLite数据库存储在内部存储空间的/data/data//databases日录下。
1. 重要的类和接口
1.1 SQLiteDatabase 常用方法
| 方法 |
描述 |
| public static SQLiteDatabase openDatabase ( String path ,SQLiteDatabase, CursorFactory, int flags ) |
以指定模式打开指定路径下的数据库文件 |
| public void execSQL( String sql) |
执行 sql 语句 |
| public void execSQL( Sting sql, Object [ ] args) |
执行 sql语句,args 为参数值数组 |
| public Cursor rawQuery ( String sql, String [ ]selection_Args) |
执行指定的 sql 查询语句 |
| public long insert ( String table, String nullColumn, Cont-entValues values ) |
向 table 表插入数据,nullCloumn为默认NULL值的列名,values为字段键值对 |
| public int update( String table, ContentValues values,String whereClause String [ ] whereArgs) |
修改table表数据,values为修改字段键值对,whereClause为where子,whereArgs为where子句参数值数组 |
| public int delete ( String table, String whereClause, String [] whereArgs) |
删除table 表数据,whereClause为where 子句whereArgs为 where 子句参数值数组 |
| public Cursor query( String table, String[]columnsString selection, String [ ]selectionArgs, String groupBy,String having, String orderBy) |
从table表查询数据,返回结果集Cursor,col-umns为列名数组,selection为where子语,selectionArgs为where子句参数值数组,groupBy为分组,having为分组过滤,orderBy为排序 |
| public void close( ) |
关闭数据库 |
1.2 Cursor 接口
SQLiteDatabase 类中 query()方法的返回值为查询结果集的Cursor游标。Cursor是一个接口,在 android.database包中,开发者可以通过遍历Cursor 的方法得到查询结果的所有记录。
Cursor 接口的常用方法
| 方法 |
功能描述 |
| public abstract getCount( ) |
获取查询结果的数量 |
| public abstract boolean isF’irst( ) |
判断结果游标是否指向第一行 |
| public abstract boolean isLast( ) |
判断结果游标是否指向最后一行 |
| public abstract boolean moveToFirst( ) |
移动游标到结果集第一行 |
| public abstract boolean moveToLast( ) |
移动游标到结果集最后一行 |
| public abstract boolean moveToNext( ) |
移动游标到结果集下一行 |
| public abstract boolean moveToPrevious( ) |
移动游标到结果集上一行 |
| public abstract int getInt( int columnIndex) |
根据列索引,获取列的整数值 |
| public abstract String getString( int columnlndex ) |
根据列索引,获取列的字符串值 |
1.3 .SQLiteOpenHelper类
SOLiteDatabase 类是一个数据库操作类,在对象实例化、数据库升级、访问对象的管理等方面使用起来具有一定的复杂性。Android 系统提供了一个数据库操作辅助类 SOLiteOpenHelper,它封装了创建和更新数据库使用的细节。它是一个抽象类,开发者可以定义其子类实现其抽象方法,辅助完成数据库的操作。
| 方法 |
描述 |
| public SQLiteOpenHepler( Context context, String name ,SQLiteDatabase. CursorFactory factory, int version ) |
构造方法,必须指明数据库名和版本号 |
| public abstract void onCreate( $QLiteDatabase db) |
抽象方法,可重写该方法,利用 ab创建表初始化数据 |
| public synchronized void close( ) |
关闭数据库 |
| public synchronized SQLiteDatabase getReadableDatabase ( ) |
以只读方式创建或者打开数据库 |
| public synchronized $QLiteDatabase getWritableDatabase( ) |
以写方式创建或者打开数据库 |
| public abstract void onUpgrade( SOLiteDatabase db, int oldVersion, int newVersion ) |
当版本号增加后,该方法被自动执行,实现数据库的升级、数据更新等 |
2. 代码实例
2.1 创建表
前面提到,使用到SQLite就需要创建到表,但是没有像mysql类似的数据库链接,只有本身提供的自带的小型数据库,所以我们按照SQLiteDataBase的基础方式创建出一个数据表,并且重写其中的OnCreat方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
|
public class StudentDBHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "student_db"; private static final String TABLE_NAME = "student"; private static final int DATABASE_VERSION = 1;
public StudentDBHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); }
@Override public void onCreate(SQLiteDatabase db) { String strSQL = "CREATE TABLE " + TABLE_NAME + " (sid INTEGER PRIMARY KEY AUTOINCREMENT, " + "stu_no VARCHAR(100), " + "name VARCHAR(100), " + "clazz VARCHAR(100), " + "publish TEXT)"; db.execSQL(strSQL); }
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
|
如果需要在创建时往其中添加一些数据就可以在创建时的OnCreat方法下面执行插入操作:
1 2 3
| String sql1 = "INSERT INTO " + TABLE_NAME + " VALUES(null, '202001', '韩1', '计算机1班', '2020-06-13')"; db.execSQL(sql1);
|
3.2 Dao持久化
要将数据等的操作加载入数据库中,就需要一个媒介,也就是上面提到的Cursor对象,其中的cursor起到一个类似推车的作用,将所有的数据都带过来,最后对这个对象中的元素进行清洗得到需要的数据
其中的查询操作需要使用到Cursor对象,更删改主要依靠execSQL对SQL语句进行提交和执行,而execSQL又是SQLiteDatabase对象中的操作,这样我们可以将其提取成一个方法来减少对对象的调用,将需要执行的sql语句提交到这个方法就可以实现对语句的执行
主要的操作都是交给execSQL这个自己的对象操作:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public boolean execSQL(final String strSQL) { try { db.beginTransaction(); db.execSQL(strSQL); db.setTransactionSuccessful(); } catch (RuntimeException e) { e.printStackTrace(); return false; } finally { db.endTransaction(); } return true; }
|
这样我们就可以将增删改查写成更加简介的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
| /** * StudentDao类用于执行与学生相关的数据库操作。 * 包括增、删、查等功能,通过SQLiteOpenHelper管理数据库。 */ public class StudentDao { private SQLiteDatabase db; // SQLiteDatabase对象,用于执行SQL命令
/** * 构造方法,初始化StudentDao对象并获取可写的数据库实例。 * * @param dbHelper SQLiteOpenHelper对象,用于管理数据库创建和版本管理 */ public StudentDao(SQLiteOpenHelper dbHelper) { db = dbHelper.getWritableDatabase(); // 获取可写数据库 }
/** * 执行查询操作,并将结果存储到给定的列表中。 * * @param list 存储查询结果的列表,使用Map来表示每一行数据 * @param strSQL 要执行的SQL查询语句 */ public void execQuery(List<Map<String, Object>> list, final String strSQL) { Cursor cursor = null; // 定义Cursor对象用于遍历查询结果 try { cursor = db.rawQuery(strSQL, null); // 执行查询 list.clear(); // 清空列表以准备存储新结果 if (cursor.moveToFirst()) { // 检查游标是否有数据 do { // 创建一个Map用于存储一行数据 Map<String, Object> map = new HashMap<>(); map.put("sid", cursor.getInt(0)); // 获取学生ID map.put("stu_no", cursor.getString(1)); // 获取学号 map.put("name", cursor.getString(2)); // 获取姓名 map.put("clazz", cursor.getString(3)); // 获取班级 map.put("publish", cursor.getString(4)); // 获取发布日期 list.add(map); // 将当前行的数据添加到列表中 } while (cursor.moveToNext()); // 移动到下一行 } } catch (RuntimeException e) { e.printStackTrace(); // 打印异常信息 } finally { if (cursor != null) { cursor.close(); // 确保游标在使用后被关闭,避免内存泄漏 } } }
/** * 执行不返回结果的SQL语句(如INSERT、DELETE等)。 * * @param strSQL 要执行的SQL语句 * @return 如果执行成功返回true,否则返回false */ public boolean execSQL(final String strSQL) { try { db.beginTransaction(); // 开始事务 db.execSQL(strSQL); // 执行SQL语句 db.setTransactionSuccessful(); // 设置事务成功 } catch (RuntimeException e) { e.printStackTrace(); // 打印异常信息 return false; // 返回执行失败 } finally { db.endTransaction(); // 结束事务 } return true; // 返回执行成功 }
/** * 添加学生信息到数据库。 * * @param stuNo 学号 * @param name 姓名 * @param clazz 班级 * @param publish 发布日期 */ public void addStudent(String stuNo, String name, String clazz, String publish) { // 构建INSERT SQL语句 String strSQL = "INSERT INTO student(stu_no, name, clazz, publish) VALUES('" + stuNo + "', '" + name + "', '" + clazz + "', '" + publish + "')"; execSQL(strSQL); // 执行SQL语句 }
/** * 根据学号删除学生信息。 * * @param stuNo 学号 */ public void deleteStudent(String stuNo) { // 构建DELETE SQL语句 String strSQL = "DELETE FROM student WHERE stu_no = '" + stuNo + "'"; execSQL(strSQL); // 执行SQL语句 }
/** * 查询学生信息,根据提供的条件过滤结果。 * * @param list 存储查询结果的列表 * @param stuNo 学号(可选) * @param name 姓名(可选) * @param clazz 班级(可选) */ public void queryStudents(List<Map<String, Object>> list, String stuNo, String name, String clazz) { StringBuilder strSQL = new StringBuilder("SELECT * FROM student WHERE 1=1 "); // 基础查询语句 if (!stuNo.isEmpty()) { strSQL.append(" AND stu_no LIKE '%").append(stuNo).append("%'"); // 添加学号过滤条件 } if (!name.isEmpty()) { strSQL.append(" AND name LIKE '%").append(name).append("%'"); // 添加姓名过滤条件 } if (!clazz.isEmpty()) { strSQL.append(" AND clazz LIKE '%").append(clazz).append("%'"); // 添加班级过滤条件 } strSQL.append(" ORDER BY publish DESC"); // 按发布日期降序排列 execQuery(list, strSQL.toString()); // 执行查询 } }
|
3.3 对象调用
完成以上创建后,基本完成了后端数据库的主要开发,剩下的就主要为前端调用的方式,我们需要创建一个初始化 StudentDao,使其能够使用 StudentDBHelper 提供的数据库访问功能。通过 StudentDao,可以执行对学生表的各种操作,例如添加、删除和查询学生记录。这样做的好处是将数据库操作的逻辑封装在 StudentDao 中,符合单一职责原则,使代码更清晰和可维护。
1
| dao = new StudentDao(new StudentDBHelper(this));
|
那么我们可以通过一下对StudnetDao中的方法进行调用:
1 2 3 4 5 6 7 8 9 10 11 12 13
| private void deleteStu(String stuNo) { dao.deleteStudent(stuNo); refreshStudentList(); }
private void refreshStudentList() { String stuNo = txtStuNo.getText().toString().trim(); String name = txtName.getText().toString().trim(); String clazz = txtClazz.getText().toString().trim(); dao.queryStudents(list, stuNo, name, clazz); adapter.notifyDataSetChanged(); }
|
4. 总结
1.首先需要对SQLiteOpenHelper进行继承实现其中的onCreate用来创建一个数据表对象
2.创建持久化dao层,私有SQLiteDatabase对象,调用SQLiteDatabase对象的增删改查方法
3.主类中新建一个SQLiteOpenHelper的实现子类并交给SQLiteDatabase的dao层管理
4.在主类中调用dao对象应用dao层实现的方法
1
| dao = new StudentDao(new StudentDBHelper(this));
|