Android中数据库SQLite用法解析

Android中数据库SQLite用法解析,第1张

概述目录1、SQLite基本使用1.1、SQLiteOpenHelper简介1.2、数据库增、删、改、查2、SQLiteDatabase增、删、改、查参数分析2.1、增2.2、删2.3、改2.4、查2.5、其他3、SQLiteDatabase事务SQLite使用可参考:https://www.runoob.com/sqlite/sqlite-tutorial.html1、SQLite基本使用1.1、

目录1、SQLite基本使用1.1、SQLiteOpenHelper简介1.2、数据库增、删、改、查2、SQLiteDatabase增、删、改、查参数分析2.1、增2.2、删2.3、改2.4、查2.5、其他3、SQLiteDatabase事务

sqlite使用可参考:https://www.runoob.com/sqlite/sqlite-tutorial.html

1、sqlite基本使用1.1、sqliteOpenHelper简介

​ sqliteOpenHelper是一个抽象类,用于辅助sqlite数据库 *** 作,必须实现构造方法、onCreate和onUpgrade。

​ (1)构造方法:

public sqliteOpenHelper(@Nullable Context context, @Nullable String name,        @Nullable CursorFactory factory, int version)public sqliteOpenHelper(@Nullable Context context, @Nullable String name,        @Nullable CursorFactory factory, int version,        @Nullable DatabaseErrorHandler errorHandler)public sqliteOpenHelper(@Nullable Context context, @Nullable String name, int version,        @NonNull sqliteDatabase.OpenParams openParams)        public sqliteOpenHelper(@Nullable Context context, @Nullable String name,        @Nullable CursorFactory factory, int version,        int minimumSupportedVersion, @Nullable DatabaseErrorHandler errorHandler)private sqliteOpenHelper(@Nullable Context context, @Nullable String name, int version,        int minimumSupportedVersion,        @NonNull sqliteDatabase.OpenParams.Builder openParamsBuilder)

​ 其中context可以传入Application的context, name为对应的数据库文件名(sqlite数据持久化需要,如果传入null, 则会创建一个内存数据库,应用结束数据会丢失), version为数据库版本,minimumSupportedVersion为数据库支持的最低版本,已存在的数据库版本低于这个版本时数据库将被删除,重新创建数据库,openParamsBuilder为数据库打开参数类sqliteDatabase.OpenParams的builder, 可配置数据库损坏监听errorHandler和用于查询时生成Cursor的cursorFactory。

​ (2)onCreate(sqliteDatabase db)方法

​ onCreate方法中一般通过sqliteDatabase类型的db,执行execsql(String sql)来实现表的创建。

​ (3)onUpgrade(sqliteDatabase db, int oldVersion, int newVersion)方法

​ oldVersion为已存在的数据库版本,newVersion为新创建的数据库版本(构造方法中传入的version),需要大于oldVersion。该方法用于数据库升级,可以添加列、修改表名等。

​ (4)onConfigure(sqliteDatabase db)、onopen(sqliteDatabase db)等

​ onConfigure在onCreate之前调用,可以启用写前日志记录或外键支持,onopen重写以执行数据库开启后的 *** 作。

​ 当已存在的数据库版本oldVerson等于0时(表示数据库不存在),会调用onCreate方法,创建相应的表;如果oldVersion小于newVersion,会调用onUpgrade方法,执行数据库升级相关 *** 作,如果oldVersion大于newVersion,会调用onDowngrade方法(需要重写onDowngrade方法),执行数据库降级 *** 作。

1.2、数据库增、删、改、查

​ (1)创建sqliteOpenHelper,用于 *** 作指定数据库中的数据

​ 新建UsersqliteHelper类,继承自sqliteOpenHelper,实现onCreate方法和onUpgrade方法,在onCreate方法中新建表,在onUpgrade中升级表。

public class UsersqliteHelper extends sqliteOpenHelper {    private static final int CURRENT_VERSION = 1;    private static final String CREATE_USER_table = "create table user(ID integer primary key autoincrement, " +            "name char(50)" +            ", age int default 18" +            ")";    private static final String DROP_USER_table = "drop table if exists user";    private UsersqliteHelper(int version) {        super(BaseApplication.getInstance(), "user.db", null, version);    }    @OverrIDe    public voID onCreate(sqliteDatabase db) {        db.execsql(CREATE_USER_table);    }    @OverrIDe    public voID onUpgrade(sqliteDatabase db, int oldVersion, int newVersion) {        //这里简单的删除原来的表,再新建表        db.execsql(DROP_USER_table);        onCreate(db);    }        private static volatile UsersqliteHelper instance;    public static UsersqliteHelper getInstance() {        if (instance == null) {            synchronized (UsersqliteHelper.class) {                if (instance == null) {                    instance = new UsersqliteHelper(CURRENT_VERSION);                }            }        }        return instance;    }}

​ 获取 *** 作数据库的sqliteDatabase

String tablename = "user";UsersqliteHelper helper = UsersqliteHelper.getInstance();sqliteDatabase writableDatabase = helper.getWritableDatabase();

​ 查询数据库中所有的记录,用于检查增、删、改、查结果

private voID queryAll(String tag, sqliteDatabase database) {    String table = "user";    Cursor cursor = database.query(table, new String[]{"name", "ID"},            null, null, null, null, null);    if (cursor == null) {        Log.d("Test" + tag, "查询全部:查询得到的cursor为空");    } else if (cursor.getCount() == 0) {        Log.d("Test" + tag, "查询全部:未查询到指定的数据");        cursor.close();    } else {        while (cursor.movetoNext()) {            String name = cursor.getString(cursor.getColumnIndex("name"));            int ID = cursor.getInt(cursor.getColumnIndex("ID"));            Log.d("Test" + tag, "查询全部:User[name = " + name + ", ID = " + ID + "]");        }        cursor.close();    }}

​ (2)新增数据

//增加数据ContentValues insert = new ContentValues();insert.put("name", "张三");writableDatabase.insert(tablename, "name", insert);queryAll("增加后", writableDatabase);

​ Logcat中输出为:

Test增加后: 查询全部:User[name = 张三, ID = 3]

​ (3)查询数据

//查询数据Cursor cursor = writableDatabase.query(tablename, new String[]{"name", "ID"}, "name = ?", new String[]{"张三"},        null, null, null);if (cursor == null) {    Log.d("Test", "查询得到的cursor为空");} else if (cursor.getCount() == 0) {    Log.d("Test", "未查询到指定的数据");    cursor.close();} else {    while (cursor.movetoNext()) {        String name = cursor.getString(cursor.getColumnIndex("name"));        int ID = cursor.getInt(cursor.getColumnIndex("ID"));        Log.d("Test", "User[name = " + name + ", ID = " + ID + "]");    }    cursor.close();}queryAll("查询后", writableDatabase);

​ Logcat中输出为:

Test: User[name = 张三, ID = 3]Test查询后: 查询全部:User[name = 张三, ID = 3]

​ (4)更新数据

//更新数据ContentValues update = new ContentValues();update.put("name", "李四");// 相当于update user set name = "李四" where name = "张三"writableDatabase.update(tablename, update, "name = ?", new String[]{"张三"}); queryAll("更新后", writableDatabase);

​ Logcat中输出为:

Test更新后: 查询全部:User[name = 李四, ID = 3]

​ (5)删除数据

//删除writableDatabase.delete(tablename, "name = ?", new String[]{"李四"});queryAll("删除后", writableDatabase);

​ Logcat中输出为:

Test删除后: 查询全部:未查询到指定的数据
2、sqliteDatabase增、删、改、查参数分析2.1、增

​ 用于插入数据的方法有三个,分别是

public long insert(String table, String nullColumnHack, ContentValues values)public long insertOrThrow(String table, String nullColumnHack, ContentValues values)public long insertWithOnConflict(String table, String nullColumnHack,            ContentValues initialValues, int conflictAlgorithm)

​ insertWithOnConflict使用conflictAlgorithm参数,指定列存在约束并且冲突时的处理,包括回滚、终止、替换等。insert方法和insertWithOrThrow都调用了insertWithOnConflict,指定了CONFliCT_NONE算法,即不做任何 *** 作。

​ insertWithOnconflict方法如下:

public long insertWithOnConflict(String table, String nullColumnHack,        ContentValues initialValues, int conflictAlgorithm) {    acquireReference();    try {        StringBuilder sql = new StringBuilder();        sql.append("INSERT");        sql.append(CONFliCT_VALUES[conflictAlgorithm]);        sql.append(" INTO ");        sql.append(table);        sql.append('(');        Object[] bindArgs = null;        int size = (initialValues != null && !initialValues.isEmpty())                ? initialValues.size() : 0;        if (size > 0) {            bindArgs = new Object[size];            int i = 0;            for (String colname : initialValues.keySet()) {                sql.append((i > 0) ? "," : "");                sql.append(colname);                bindArgs[i++] = initialValues.get(colname);            }            sql.append(')');            sql.append(" VALUES (");            for (i = 0; i < size; i++) {                sql.append((i > 0) ? ",?" : "?");            }        } else {            sql.append(nullColumnHack + ") VALUES (NulL");        }        sql.append(')');        sqliteStatement statement = new sqliteStatement(this, sql.toString(), bindArgs);        try {            return statement.executeInsert();        } finally {            statement.close();        }    } finally {        releaseReference();    }}

​ 以上可以看出,该方法就是根据各参数,生成SQL语句,然后执行插入 *** 作,其中SQL语句如下: insert 参数1 into 参数2 ( 参数3 ) , 其中

​ 参数1为插入数据存在冲突时使用的算法,为String[] CONFliCT_VALUES = new String[] {"", " OR RolLBACK ", " OR ABORT ", " OR FAIL ", " OR IGnorE ", " OR REPLACE "}中的一个,

​ 参数2为要插入数据对应的表, 上面示例中为user,

​ 参数3为具体的数据, 假设initialValues中有name和age两个字段(initialValues为空的情况,会插入一条数据,nullColumnHack指定的列值为null),分别为张三、30, 则参数3 为 name, age) values(?, ? , 对应的bindArgs为{"张三", 30}。

​ 于是要执行的SQL语句为insert or replace into user ( name, age) values(?, ? ),对应的参数bindArgs为{"张三", 30},传入sqliteStatement, 调用executeInsert()方法以执行对应的插入语句。。

2.2、删

​ 用于删除的方法有一个:

public int delete(String table, String whereClause, String[] whereArgs) {        acquireReference();        try {            sqliteStatement statement =  new sqliteStatement(this, "DELETE FROM " + table +                    (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);            try {                return statement.executeUpdateDelete();            } finally {                statement.close();            }        } finally {            releaseReference();        }    }

​ 方法有三个参数table、whereClause、whereArgs,其中table表示要 *** 作的表名, whereClause格式类似于 ID = ? and name = ?,数组whereArgs提供占位符?对应的参数,传入sqliteStatement, 调用executeUpdateDelete以执行delete from table where ID = ? and name = ?语句,对应的参数为whereArgs。如果whereClause为空字符串或null, 则会执行delete from table,会将表中所有的数据删除。

2.3、改

​ 用于更新的方法有两个:

public int update(String table, ContentValues values, String whereClause, String[] whereArgs)public int updateWithOnConflict(String table, ContentValues values,        String whereClause, String[] whereArgs, int conflictAlgorithm) 

​ 其中update(String, ContentValues, String, String[])方法调用了updateWithOnConflict(String, ContentValues, String, String[], int), 最后一个参数指定数据冲突时的算法,和insert相关的方法中相同。

​ updateWithOnConflict(String, ContentValues, String, String[], int)方法如下:

public int updateWithOnConflict(String table, ContentValues values,            String whereClause, String[] whereArgs, int conflictAlgorithm) {        if (values == null || values.isEmpty()) {            throw new IllegalArgumentException("Empty values");        }        acquireReference();        try {            StringBuilder sql = new StringBuilder(120);            sql.append("UPDATE ");            sql.append(CONFliCT_VALUES[conflictAlgorithm]);            sql.append(table);            sql.append(" SET ");            // move all bind args to one array            int setValuesSize = values.size();            int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length);            Object[] bindArgs = new Object[bindArgsSize];            int i = 0;            for (String colname : values.keySet()) {                sql.append((i > 0) ? "," : "");                sql.append(colname);                bindArgs[i++] = values.get(colname);                sql.append("=?");            }            if (whereArgs != null) {                for (i = setValuesSize; i < bindArgsSize; i++) {                    bindArgs[i] = whereArgs[i - setValuesSize];                }            }            if (!TextUtils.isEmpty(whereClause)) {                sql.append(" WHERE ");                sql.append(whereClause);            }            sqliteStatement statement = new sqliteStatement(this, sql.toString(), bindArgs);            try {                return statement.executeUpdateDelete();            } finally {                statement.close();            }        } finally {            releaseReference();        }    }

​ 和insertWithOnConflict类似, 该方法也是将参数拼接成SQL语句:update 参数1 参数2 set 参数3 where 参数4, 其中:

​ 参数1为更新数据存在冲突时使用的算法,为String[] CONFliCT_VALUES = new String[] {"", " OR RolLBACK ", " OR ABORT ", " OR FAIL ", " OR IGnorE ", " OR REPLACE "}中的一个,

​ 参数2为要更新数据对应的表, 上面示例中为user,

​ 参数3为具体需要更新字段拼接的字符串,假设ContentValues中有name和age两个字段,分别为张三、30, 则参数3 为 name=? , age = ? , 对应的bindArgs为{"张三", 30}。

​ 参数4为对应的查询条件,对应String whereClause参数,类似于**ID = 20 and name =李四 **等查询条件, 以指定具体需要更新的数据。

​ 于是,具体的SQL语句为:update or replace user set name=?, age = ? where ID = 20 and name = 李四, 对应的参数bindArgs为{"张三", 30}, 传入sqliteStatement, 调用executeUpdateDelete()方法以执行对应的更新语句。

2.4、查

​ (1) 使用参数的查询方法有:

public Cursor query(boolean distinct, String table, String[] columns,            String selection, String[] selectionArgs, String groupBy,            String having, String orderBy, String limit)            public Cursor query(boolean distinct, String table, String[] columns,            String selection, String[] selectionArgs, String groupBy,            String having, String orderBy, String limit, CancellationSignal cancellationSignal)            public Cursor query(String table, String[] columns, String selection,            String[] selectionArgs, String groupBy, String having,            String orderBy)            public Cursor query(String table, String[] columns, String selection,            String[] selectionArgs, String groupBy, String having,            String orderBy, String limit)public Cursor queryWithFactory(CursorFactory cursorFactory,            boolean distinct, String table, String[] columns,            String selection, String[] selectionArgs, String groupBy,            String having, String orderBy, String limit)            public Cursor queryWithFactory(CursorFactory cursorFactory,            boolean distinct, String table, String[] columns,            String selection, String[] selectionArgs, String groupBy,            String having, String orderBy, String limit, CancellationSignal cancellationSignal)                        

​ 最上面五个方法是对最后一个方法queryWithFactory的调用,也是通过拼接SQL语句再执行来完成查询 *** 作的,方法如下:

public Cursor queryWithFactory(CursorFactory cursorFactory,        boolean distinct, String table, String[] columns,        String selection, String[] selectionArgs, String groupBy,        String having, String orderBy, String limit, CancellationSignal cancellationSignal) {    acquireReference();    try {        String sql = sqlitequeryBuilder.buildqueryString(                distinct, table, columns, selection, groupBy, having, orderBy, limit);        return rawqueryWithFactory(cursorFactory, sql, selectionArgs,                findEdittable(table), cancellationSignal);    } finally {        releaseReference();    }}

​ 其中,调用了sqlitequeryBuilder的buildqueryString方法来拼接SQL语句,如下:

public static String buildqueryString(        boolean distinct, String tables, String[] columns, String where,        String groupBy, String having, String orderBy, String limit) {    if (TextUtils.isEmpty(groupBy) && !TextUtils.isEmpty(having)) {        throw new IllegalArgumentException(                "HAVING clauses are only permitted when using a groupBy clause");    }    if (!TextUtils.isEmpty(limit) && !slimitPattern.matcher(limit).matches()) {        throw new IllegalArgumentException("invalID liMIT clauses:" + limit);    }    StringBuilder query = new StringBuilder(120);    query.append("SELECT ");    if (distinct) {        query.append("disTINCT ");    }    if (columns != null && columns.length != 0) {        appendColumns(query, columns);    } else {        query.append("* ");    }    query.append("FROM ");    query.append(tables);    appendClause(query, " WHERE ", where);    appendClause(query, " GROUP BY ", groupBy);    appendClause(query, " HAVING ", having);    appendClause(query, " ORDER BY ", orderBy);    appendClause(query, " liMIT ", limit);    return query.toString();}

​ 最终将SQL语句拼接成如下格式(参数1为所需查询列拼接的字符串):SELECT distinct 参数1 FROM table WHERE selection GROUP BY groupBy HAVING having ORDER BY orderBy liMIT limit。从查询语句来看,之前列出的查询方法都可以进行多表查询,示例如下:

//增加数据ContentValues values = new ContentValues();values.put("name", "张三");writableDatabase.insert("user", "name", values);writableDatabase.insert("user1", "name", values);//查询数据Cursor cursor = writableDatabase.query(true, "user,user1",        new String[]{"user.name", "user.ID", "user1.name", "user1.ID"},        "user.name = ? and user1.name = ?", new String[]{"张三", "张三"},        null, null, null, null);if (cursor == null) {    Log.d("Test", "查询得到的cursor为空");} else if (cursor.getCount() == 0) {    Log.d("Test", "未查询到指定的数据");    cursor.close();} else {    while (cursor.movetoNext()) {        String name = cursor.getString(cursor.getColumnIndex("user.name"));        int ID = cursor.getInt(cursor.getColumnIndex("user.ID"));        String name1 = cursor.getString(cursor.getColumnIndex("user1.name"));        int ID1 = cursor.getInt(cursor.getColumnIndex("user1.ID"));        Log.d("Test", "name = " + name + ", ID = " + ID + ", name1 = " + name1 + ", ID1 = " + ID1);    }    cursor.close();}

​ (2)直接使用sql的查询方法有:

public Cursor rawquery(String sql, String[] selectionArgs)public Cursor rawquery(String sql, String[] selectionArgs,            CancellationSignal cancellationSignal)            public Cursor rawqueryWithFactory(            CursorFactory cursorFactory, String sql, String[] selectionArgs,            String edittable)            public Cursor rawqueryWithFactory(            CursorFactory cursorFactory, String sql, String[] selectionArgs,            String edittable, CancellationSignal cancellationSignal)            

​ 直接通过SQL语句来进行查询,可以进行多表复合查询,sql对对应的查询语句, selectionArgs为占位符?对应的参数数组。

2.5、其他

​ sqliteDatabase除了增删改查之外, 还可以执行其他语句,包括创建表、删除表、重命名表、添加列等等。

public voID execsql(String sql) throws sqlException {    executesql(sql, null);}public voID execsql(String sql, Object[] bindArgs) throws sqlException {        if (bindArgs == null) {            throw new IllegalArgumentException("Empty bindArgs");        }        executesql(sql, bindArgs);}public int executesql(String sql, Object[] bindArgs) {   ...}
3、sqliteDatabase事务

​ 某种情况下,需要执行一系列 *** 作时,确保这些 *** 作同时成功,或者同时失败,数据库中能够保证这些 *** 作同时成功或同时失败的执行单元称为事务,典型的代码如下:

   sqliteDatabase.beginTransaction();   try {      ...      sqliteDatabase.setTransactionSuccessful();   } finally {      sqliteDatabase.endTransaction();   }

​ sqliteDatabase的beginTransaction()方法标识一个事务的开始, setTransactionSuccessful()表示增删改查等 *** 作成功,endTransaction()方法表示结束一个事务,此时修改将被提交到数据库。如果过程中产生异常,则不会调用setTransactionSuccessful(),中间的各种 *** 作将被还原。

​ 事务开始标识有如下方法:

public voID beginTransaction() {    beginTransaction(null /* transactionStatusCallback */, true);}public voID beginTransactionNonExclusive() {    beginTransaction(null /* transactionStatusCallback */, false);}public voID beginTransactionWithListener(sqliteTransactionListener transactionListener) {    beginTransaction(transactionListener, true);}public voID beginTransactionWithListenerNonExclusive(        sqliteTransactionListener transactionListener) {    beginTransaction(transactionListener, false);}private voID beginTransaction(sqliteTransactionListener transactionListener,        boolean exclusive) {    acquireReference();    try {        getThreadSession().beginTransaction(                exclusive ? sqliteSession.TRANSACTION_MODE_EXCLUSIVE :                        sqliteSession.TRANSACTION_MODE_IMMEDIATE,                transactionListener,                getThreadDefaultConnectionFlags(false /*Readonly*/), null);    } finally {        releaseReference();    }}

​ 其中sqliteTransactionListener为事务执行过程监听接口,可以监测到事务具体的执行情况:onBegin、onCommit、onRoolback, 分别表示开始、提交、还原。

public interface sqliteTransactionListener {    /**     * Called immediately after the transaction begins.     */    voID onBegin();    /**     * Called immediately before commiting the transaction.     */    voID onCommit();    /**     * Called if the transaction is about to be rolled back.     */    voID onRollback();}

总结:以上简要分析了sqliteDatabase的用法,包括增删改查等, 还有就是sqlite事务在安卓中的应用。

总结

以上是内存溢出为你收集整理的Android中数据库SQLite用法解析全部内容,希望文章能够帮你解决Android中数据库SQLite用法解析所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1016543.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存