【Android】数据存储全方案之SQLite初体验

作者:邹峰立,微博:zrunker,邮箱:zrunker@yahoo.com,微信公众号:书客创作,个人平台:www.ibooker.cc

本文选自书客创作平台第8篇文章。阅读原文

《【Android】数据存储全方案之SQLite初体验》 书客创作

SQLite是一个轻型级、嵌入式、ACID关系型数据库(A-原子性,C-一致性,I-隔离性,D-持久性),第一个Alpha版本诞生于2000年5月,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用,如QQ,迅雷等,它占用资源非常少,在嵌入式设备中,可能只需要几百KB的内存就够了,完全可以把SQLite当作一个API来进行使用。

SQLite数据库是D.Richard Hipp用C语言编写的开源嵌入式数据库,支持数据库大小2TB。它具有以下特征:

1、轻量级

SQLite与其他数据库不同,它是进程内的数据库引擎,因此不存在数据库的客户端和服务端。使用SQLite一般只需要带上它的动态库(sqlite.dll),就能够使用其全部功能,该动态库大约几百KB。

2、独立性

SQLite数据库的核心引擎本身不依赖第三方软件,使用它不需要安装即可使用,十分方便。

3、隔离性

SQLite所有信息都在一个文件中,包括表,视图,索引等,该文件可以在任何平台打开,方便管理和维护。

4、跨平台

SQLite支持大部分的操作系统,Windows、Android、Windows Mobile、Symbin、Palm等。

5、多语言接口

SQLite数据库支持很多语言编程接口,如C/C++、Java、Python、dotNet、Ruby、Perl等。

6、安全性

SQLite具有单一文件性,所以在执行数据写入操作的时候,它就会把整个文件进行加锁,这就意味着在一个线程执行数据库写入操作的时候,其他线程将无法操作,从而保证数据的安全性。

SQLite编程解析

一般对SQLite数据库SQL操作都是使用SQLiteDatabase进行处理,SQLiteDatabase是Android平台上提供的一个处理SQLite数据库的工具类。

初始化SQLiteDatabase:(常用两个方法)

/**
 * 方式一:创建或打开数据库
 * @param file 数据库文件
 * @param factory 游标工厂,一般设置为null即可
 */
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(File file, SQLiteDatabase.CursorFactory factory);

/**
 * 方式二:打开数据库
 * @param path 数据库存放路径
 * @param factory 游标工厂,一般设置为null即可
 * @param flags 数据库操作模式,一般指定值有两个SQLiteDatabase.OPEN_READWRITE(可读可写)或SQLiteDatabase.OPEN_READONLY(只读)
 */
SQLiteDatabase db = SQLiteDatabase.openDatabase(String path, SQLiteDatabase.CursorFactory factory, int flags);

对数据库的操作无外乎增删改查,SQLite提供了专门的API来实现这些功能。假设:在SD卡中有一个数据库ibookerdata.db文件,通过对该文件的操作来实现数据库的增删改查。

// 实例:初始化SQLiteDataBase
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "ibookerdata.db";
SQLiteDatabase db = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READWRITE);

1、创建表:创建一个t_user表。

// 创建t_user表
String create_user = "CREATE TABLE IF NOT EXISTS t_user(_id INTEGER PRIMARY KEY autoincrement,u_id BIGINT UNSIGNED NOT NULL UNIQUE,u_phone BIGINT NOT NULL UNIQUE,u_realname VARCHAR(21),u_sex VARCHAR(6),u_height FLOAT(5,2),u_weight FLOAT(6,2),u_birthday VARCHAR(10),u_domicile VARCHAR(50),u_email VARCHAR(40),u_weibo VARCHAR(40))";
// 执行sql语句
db.execSQL(create_user);

2、插入数据

/**
 * 方式一:通过SQLite API实现插入数据功能,返回插入成功之后的行ID值
 * @param table 表名
 * @param nullColumnHack 如果没有指定列值时,使用null表示,但不允许全部为null
 * @param values 键值对集合,列名+列值
 */
long insert(String table, String nullColumnHack, ContentValues values);
// 实例
ContentValues insert_values = new ContentValues();
insert_values.put("u_id", 1102);
insert_values.put("u_phone", 18011111254L);
...
insert_values.put("u_weibo", "@zrunker");
db.insert("t_user", null, insert_values);

/**
 * 方式二:通过执行SQL语句实现插入数据功能
 * @param sql 待执行SQL语句
 * @param bindArgs 通配符对应数据集
 */
void execSQL(String sql, Object[] bindArgs) throws SQLException;
// 实例
String insert_sql = "insert into t_user(u_id, u_phone,  u_realname, u_sex ,u_height ,u_weight ,u_birthday, u_domicile, u_email ,u_weibo) values(?,?,?,?,?,?,?,?,?,?)";
db.execSQL(insert_sql, new Object[]{1102, 18011111254L, "zrunker", "男", 175, 65, "1992-10-13", "fujian", "zrunker@xx.com", "@zrunker"});

3、修改数据

/**
 * 方式一:通过SQLite API实现修改数据功能,返回修改成功行数
 * @param table 表名
 * @param values 键值对集合,列名+列值
 * @param whereClause 当前修改条件,where子句
 * @param whereArgs 修改条件占位符
 */
int update(String table, ContentValues values, String whereClause, String[] whereArgs);
// 实例
ContentValues update_values = new ContentValues();
update_values .put("u_phone", 15300025864L);
...
update_values .put("u_weibo", "zrunker");
db.update("t_user", update_values, "u_id=?", new String[]{"1102"});

/**
 * 方式二:通过执行SQL语句实现修改数据功能
 * @param sql  待执行SQL语句
 * @param bindArgs 通配符对应数据集
 */
void execSQL(String sql, Object[] bindArgs) throws SQLException;
// 实例
String update_sql = "update t_user set u_phone=? ,u_realname=?, u_sex=? ,u_height=? ,u_weight=? ,u_birthday=?, u_domicile=?, u_email=? ,u_weibo=? where u_id = ?";
db.execSQL(update_sql, new Object[]{15300025864L, "zrunker1", "女", 173, 62, "1999-10-16", "beijing", "zrunker1@aa.com", "zrunker", 1102});

4、删除数据

/**
 * 方式一:通过SQLite API实现删除数据功能,返回删除成功行数
 * @param table 表名
 * @param whereClause 当前删除条件,where子句
 * @param whereArgs 删除条件占位符
 */
int delete(String table, String whereClause, String[] whereArgs);
// 实例
db.delete("t_user", "u_id=?", new String[]{"1102"});

/**
 * 方式二:通过执行SQL语句实现删除数据功能
 * @param sql  待执行SQL语句
 * @param bindArgs 通配符对应数据集
 */
void execSQL(String sql, Object[] bindArgs) throws SQLException;
// 实例
String delete_sql = "delete from t_user where u_id=?";
db.execSQL(delete_sql, new Long[]{1102L});

5、查询数据

/**
 * 方式一:通过SQL语句执行查询功能
 * @param sql 待执行的sql语句
 * @param selectionArgs 查询条件占位符
 */
Cursor rawQuery(String sql, String[] selectionArgs);
// 实例:定义类User,作为t_user的关系映射对象
Cursor cursor = db.rawQuery("select * from t_user", null);
List<User> users = new ArrayList<>();
while (cursor.moveToNext()) {
    User user = new User();
    user.setuId(cursor.getLong(cursor.getColumnIndex("u_id")));
    user.setuPhone(cursor.getLong(cursor.getColumnIndex("u_phone")));
    user.setuRealName(cursor.getString(cursor.getColumnIndex("u_realname")));
    user.setuSex(cursor.getString(cursor.getColumnIndex("u_sex")));
    user.setuHeight(cursor.getFloat(cursor.getColumnIndex("u_height")));
    user.setuWeight(cursor.getFloat(cursor.getColumnIndex("u_weight")));
    user.setuBirthday(cursor.getString(cursor.getColumnIndex("u_birthday")));
    user.setuDomicile(cursor.getString(cursor.getColumnIndex("u_domicile")));
    user.setuEmail(cursor.getString(cursor.getColumnIndex("u_email")));
    user.setuWeibo(cursor.getString(cursor.getColumnIndex("u_weibo")));
    users.add(user);
}
cursor.close();

/**
 * 方式二:通过SQLite API进行查询操作
 * @param table 表名
 * @param columns 查询表中字段名称,null-查询所有
 * @param selection 表示查询条件,where子句
 * @param selectionArgs 表示查询条件占位符的取值
 * @param groupBy 表示分组条件,group by子句
 * @param having 表示筛选条件,having 子句
 * @param orderBy 排序,order by 子句
 * @param limit 分页查询,limit 子句
 */
Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit);
// 实例:定义类User,作为t_user的关系映射对象
Cursor cursor = db.query("t_user", null, null, null, null, null, "u_id desc", "0, 15");
...
cursor .close();

6、关闭数据库

// 在SQLiteDataBase执行完之后,一定要将其关闭
db.close();

7、删除指定表

String sql_drop_table_user = "DROP TABLE IF EXISTS t_user";
db.execSQL(sql_drop_table_user );

8、删除数据库

boolean deleteDatabase(String name);
// 实例
this.deleteDatabase("ibookerdata.db");

SQLiteOpenHelper的使用

在实际开发当中为了更好的管理和维护数据库,Android平台提供了一个叫做SQLiteOpenHelper的类进行数据库操作。利用SQLiteOpenHelper可以很方便的实现数据库的创建,管理,升级维护等一系列操作。

通过在使用SQLiteOpenHelper的时候,是将其进行二次封装,这样才能够更好的实现相应的功能。那么SQLiteOpenHelper该如何进行封装?

目标:SQLiteHelper类中要实现数据库的管理,升级维护等功能。

分析:

1、对于数据库的管理,SQLiteDatabase是相当重要的一个类,SQLiteDatabase不仅仅可以提供对数据库中表的增删改查功能,还关系到数据库的打开和关闭,所以要在SQLiteHelper类中要对SQLiteDatabase进行相应的封装。

2、对于数据库的升级维护,SQLiteOpenHelper提供一个onUpgrade方法,用来进行数据库升级时候进行相应处理工作,所以需要复写onUpgrade方法,进行相应的操作。

3、SQLite是单一文件进行操作,每一个进行写入操作时,该文件就会被锁,所以无法进行多线程同时操作数据库,如何解决并发问题呢?可以通过AtomicInteger来解决这一问题,每一次要进行数据库操作的时候,都对数据库是否可使用进行判断,可以使用才进行相应操作。

4、因为SQLiteHelper是频繁使用的一个类,所以采用单例模式,获取SQLiteHelper对象。

具体该如何实现SQLiteHelper类?

首先定义一个SQLiteHelper类,继承SQLiteOpenHelper,而SQLiteOpenHelper是一个抽象类,除了需要实现构造方法之外,还要实现onCreate(SQLiteDatabase db)和onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)这两个方法。

实现构造方法

构造方法有两个,为了实现方便一般采用只有一个参数Context的构造方法,然后让该构造方法调用多个参数的构造方法。

/**
 * 构造函数
 *
 * @param context 上下文对象
 * @param name    创建数据库的名称
 * @param factory 游标工厂
 * @param version 创建数据库版本 >= 1
 */
private SQLiteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
   super(context, name, factory, version);
}

private SQLiteHelper(Context context) {
   // 创建数据库
   this(context, SQLiteConstant.DB_NAME, null, SQLiteConstant.DB_VERSION);
}

注:SQLiteConstant.DB_NAME和SQLiteConstant.DB_VERSION分别表示数据库名和数据库版本,这里采用的是定义一个常量类SQLiteConstant,来管理数据库当中的相关常量。

实现SQLiteDatabase管理

在这里SQLiteDatabase主要是用来对外提供数据库操作对象,同时结合AtomicInteger避免数据库锁异常。其中SQLiteHelper.getWritableDatabase()是获取一个可读可写的数据库。

private AtomicInteger mOpenCounter = new AtomicInteger(0);
private SQLiteDatabase mDatabase;

/**
 * 打开数据库
 */
synchronized SQLiteDatabase openDatabase() {
    if (mOpenCounter.incrementAndGet() == 1) {
        mDatabase = SQLiteHelper.getWritableDatabase();
    }
    return mDatabase;
}

/**
 * 关闭数据库
 */
synchronized void closeDatabase() {
    if (mOpenCounter.decrementAndGet() == 0) {
        mDatabase.close();
    }
}

复写onCreate方法

/**
 * 当数据库创建时回调的函数
 *
 * @param db 数据库对象
 */
@Override
public void onCreate(SQLiteDatabase db) {
    // 创建数据表
   db.execSQL(SQLiteConstant.SQL_CREATE_TABLE_USER);
}

注意:SQLiteConstant.SQL_CREATE_TABLE_USER是常量类SQLiteConstant中常量,用来创建t_user表。

复写onUpgrade方法

/**
 * 当数据库版本更新的时候回调函数
 *
 * @param db         数据库对象
 * @param oldVersion 数据库旧版本
 * @param newVersion 数据库新版本
 */
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (newVersion > oldVersion) {
        AbstractMigratorHelper migratorHelper = new DBMigrationHelper();
        migratorHelper.onUpgrade(db);
    }

//        /* i represent the version where the user is now and the class named with this number implies that is upgrading from i to i++ schema */
//        for (int i = oldVersion; i < newVersion; i++) {
//            try {
//                /* New instance of the class that migrates from i version to i++ version named DBMigratorHelper{version that the db has on this moment} */
//                AbstractMigratorHelper migratorHelper = (AbstractMigratorHelper) Class.forName("cc.ibooker.dbupgrade.DBMigrationHelper" + i).newInstance();
//                if (migratorHelper != null) {
//                    /* Upgrade de db */
//                    migratorHelper.onUpgrade(db);
//                }
//            } catch (ClassNotFoundException | ClassCastException | IllegalAccessException | InstantiationException e) {
//                /* If something fail prevent the DB to be updated to future version if the previous version has not been upgraded successfully */
//                break;
//            }
//        }
}

注意:该方法是数据进行升级的时候进行回调的方法,数据升级主要操作是将旧表进行删除,重新构造新表,同时需要将旧表数据拷贝到新表当中,也可以进行其他方面的操作。在这里可以将数据库升级需要操作的内容写入一个叫做DBMigrationHelper的抽象类中,通过AbstractMigratorHelper是用来实现DBMigrationHelper抽象类。

/**
 * 抽象类用于数据库升级
 * Created by 邹峰立 on 2017/9/24 0024.
 */
public abstract class AbstractMigratorHelper {
    public abstract void onUpgrade(SQLiteDatabase db);
}
/**
 * 数据库升级实现类
 * Created by 邹峰立 on 2017/9/24 0024.
 */
public class DBMigrationHelper extends AbstractMigratorHelper {
    @Override
    public void onUpgrade(SQLiteDatabase db) {
        db.beginTransaction();
        try {
            // 创建t_user临时表t_user2
            db.execSQL(SQLiteConstant.SQL_CREATE_TABLE_USER2);
            // 复制t_user到t_user2
            db.execSQL(SQLiteConstant.SQL_COPY_TABLE_USER_USER2);
            // 删除t_user
            db.execSQL(SQLiteConstant.SQL_DROP_TABLE_USER);
            // 重命名t_user2为t_user
            db.execSQL(SQLiteConstant.SQL_USER2_RENAME_USER);
            // 也可以额外进行其他操作
            // ...
            db.setTransactionSuccessful();
        }catch (Exception e) {
            e.printStackTrace();
        } finally {
            db.endTransaction();
        }
    }
}

补充:对于升级数据库这一标题,可能对于大多数人来说,即熟悉又陌生。经常用,但是不知道所以然。如果如果弄清楚以下几个问题,可能就不再陌生。

为什么要进行升级?

旧版本应用程序的数据库不再满足新版本应用程序的要求,这个时候就要进行数据库升级。例如:应用程序升级后,旧版本应用程序的数据库依旧存在,但是新版本应用程序中需要新加一张表或者修改表中的一些字段,这个时候旧版本应用程序的数据库不能满足新版本应用程序的要求,所以就要对旧版本应用程序的数据库进行升级操作,以达到满足新版本应用程序的要求。

怎么判断什么时候升级?

Android平台提供一个SQLiteOpenHelper的抽象类,通过该抽象类中的onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)方法,可以实现数据库版本升级。

在SQLiteOpenHelper构造方法中有一个参数version表示数据库版本,在新版本的应用程序中,可以设置一个新的version参数值。当应用程序升级后,操作数据库时,发现数据库版本与当前数据库要求版本不一致,这个时候就会执行onUpgrade方法,这个时候就可以进行相应的操作,数据库也会自动存储最新的版本号为当前数据库版本号。

怎么升级?

一般在执行数据库升级时,要注意两点:

  • 修改数据库,如增加表,修改表字段等。
  • 备份数据,拷贝数据。
    简单一点来说,就是修改数据库,不忘数据。这一过程一般都需要创建临时表进行数据备份,然后创建新表,拷贝数据,最后删除临时表。

单例模式

private static SQLiteHelper SQLiteHelper;
/**
 * 获取MySqliteHelper,单列模式
 *
 * @param context 上下文对象
 */
static synchronized SQLiteHelper getSqliteHelper(Context context) {
    if (SQLiteHelper == null)
        SQLiteHelper = new SQLiteHelper(context);
    return SQLiteHelper;
}

常量类

/**
 * SQLite常量类
 * Created by 邹峰立 on 2017/2/16 0016.
 */
public class SQLiteConstant {
    public static final String DB_NAME = "ibookerdata.db"; //数据库名称
    public static final int DB_VERSION = 1; //数据库版本号
    // 创建User表的SQL语句
    public static final String SQL_CREATE_TABLE_USER = "CREATE TABLE IF NOT EXISTS t_user(_id INTEGER PRIMARY KEY autoincrement,u_id BIGINT UNSIGNED NOT NULL UNIQUE,u_phone BIGINT NOT NULL UNIQUE,u_realname VARCHAR(21),u_sex VARCHAR(6),u_height FLOAT(5,2),u_weight FLOAT(6,2),u_birthday VARCHAR(10),u_domicile VARCHAR(50),u_email VARCHAR(40),u_weibo VARCHAR(40))";
    // 删除User表的SQL语句
    public static final String SQL_DROP_TABLE_USER = "DROP TABLE IF EXISTS t_user";
    // 创建User临时表t_user2
    public static final String SQL_CREATE_TABLE_USER2 = "CREATE TABLE IF NOT EXISTS t_user2(_id INTEGER PRIMARY KEY autoincrement,u_id BIGINT UNSIGNED NOT NULL UNIQUE,u_phone BIGINT NOT NULL UNIQUE,u_realname VARCHAR(21),u_sex VARCHAR(6),u_height FLOAT(5,2),u_weight FLOAT(6,2),u_birthday VARCHAR(10),u_domicile VARCHAR(50),u_email VARCHAR(40),u_weibo VARCHAR(40))";
    // 复制t_user数据到t_user2
    public static final String SQL_COPY_TABLE_USER_USER2 = "INSERT INTO t_user2(_id, u_id, u_phone, u_realname, u_sex, u_height, u_weight, u_birthday, u_domicile, u_email, u_weibo)" +
            "SELECT _id, u_id, u_phone, u_realname, u_sex, u_height, u_weight, u_birthday, u_domicile, u_email, u_weibo FROM t_user";
    // 删除User临时表t_user2
    public static final String SQL_DROP_TABLE_USER2 = "DROP TABLE IF EXISTS t_user2";
    // User临时表t_user2重命名t_user
    public static final String SQL_USER2_RENAME_USER = "ALTER TABLE t_user2 RENAME TO t_user";
}

User关系映射对象

/**
 * 用户-实体类
 * Created by 邹峰立 on 2017/9/23 0023.
 */
public class User {
    private long uId;
    private String uRealName;
    private String uSex;
    private String uBirthday;
    private float uHeight;
    private float uWeight;
    private String uDomicile;
    private long uPhone;
    private String uEmail;
    private String uWeibo;

    public User() {
        super();
    }

    public User(long uId, String uRealName, String uSex, String uBirthday, float uHeight, float uWeight, String uDomicile, long uPhone, String uEmail, String uWeibo) {
        this.uId = uId;
        this.uRealName = uRealName;
        this.uSex = uSex;
        this.uBirthday = uBirthday;
        this.uHeight = uHeight;
        this.uWeight = uWeight;
        this.uDomicile = uDomicile;
        this.uPhone = uPhone;
        this.uEmail = uEmail;
        this.uWeibo = uWeibo;
    }

    // 实现变量getter/setter方法
}

SQLiteHelper类算是全部 完成了,那么该如何利用SQLiteHelper实现SQLite的相关内容呢?SQLite是一种数据库,对数据库的操作可以封装DAO层进行处理,那么该如何进行DAO层的封装和实现呢?

首先定义接口,在该接口中封装了对表t_user的相应操作。

/**
 * 数据库访问接口
 * Created by 邹封立 on 2017/2/16 0016.
 */
public interface SQLiteDao {

    /**
     * 获取用户集合
     */
    List<User> selectUser();

    /**
     * 根据用户ID获取用户信息
     *
     * @param uId 用户ID
     */
    User selectUserByuId(long uId);

    /**
     * 根据用户ID修改用户信息
     */
    void updateUserByuId(User user);

    /**
     * 插入用户信息
     */
    void insertUser(User user);

    /**
     * 根据用户ID删除用户ID
     *
     * @param uId 用户ID
     */
    void deleteUserByUid(long uId);
}

其次实现接口

/**
 * 数据库访问接口实现类,注意在修改方法前加上synchronized(同步)
 * Created by 邹峰立 on 2017/2/16 0016.
 */
public class SQLiteDaoImpl implements SQLiteDao {
    private SQLiteHelper dbHelper = null;

    /**
     * 构造方法
     *
     * @param context 上下文对象
     */
    public SQLiteDaoImpl(@NonNull Context context) {
        dbHelper = SQLiteHelper.getSqliteHelper(context);
    }

    /**
     * 获取用户集合
     */
    @Override
    public synchronized List<User> selectUser() {
        SQLiteDatabase db = dbHelper.openDatabase(); // 获取一个可读的数据库
        Cursor cursor = db.rawQuery("select * from t_user", null);
        List<User> users = new ArrayList<>();
        while (cursor.moveToNext()) {
            User user = new User();
            user.setuId(cursor.getLong(cursor.getColumnIndex("u_id")));
            user.setuPhone(cursor.getLong(cursor.getColumnIndex("u_phone")));
            user.setuRealName(cursor.getString(cursor.getColumnIndex("u_realname")));
            user.setuSex(cursor.getString(cursor.getColumnIndex("u_sex")));
            user.setuHeight(cursor.getFloat(cursor.getColumnIndex("u_height")));
            user.setuWeight(cursor.getFloat(cursor.getColumnIndex("u_weight")));
            user.setuBirthday(cursor.getString(cursor.getColumnIndex("u_birthday")));
            user.setuDomicile(cursor.getString(cursor.getColumnIndex("u_domicile")));
            user.setuEmail(cursor.getString(cursor.getColumnIndex("u_email")));
            user.setuWeibo(cursor.getString(cursor.getColumnIndex("u_weibo")));
            users.add(user);
        }
        cursor.close();
        dbHelper.closeDatabase();
        return users;
    }

    /**
     * 根据用户ID获取用户信息
     *
     * @param uId 用户ID
     */
    @Override
    public synchronized User selectUserByuId(long uId) {
        SQLiteDatabase db = dbHelper.openDatabase(); // 获取一个可读的数据库
        String sql = "select * from t_user where u_id=?";
        Cursor cursor = db.rawQuery(sql, new String[]{uId + ""});
        User user = null;
        while (cursor.moveToNext()) {
            user = new User();
            user.setuId(cursor.getLong(cursor.getColumnIndex("u_id")));
            user.setuPhone(cursor.getLong(cursor.getColumnIndex("u_phone")));
            user.setuRealName(cursor.getString(cursor.getColumnIndex("u_realname")));
            user.setuSex(cursor.getString(cursor.getColumnIndex("u_sex")));
            user.setuHeight(cursor.getFloat(cursor.getColumnIndex("u_height")));
            user.setuWeight(cursor.getFloat(cursor.getColumnIndex("u_weight")));
            user.setuBirthday(cursor.getString(cursor.getColumnIndex("u_birthday")));
            user.setuDomicile(cursor.getString(cursor.getColumnIndex("u_domicile")));
            user.setuEmail(cursor.getString(cursor.getColumnIndex("u_email")));
            user.setuWeibo(cursor.getString(cursor.getColumnIndex("u_weibo")));
        }
        cursor.close();
        dbHelper.closeDatabase();
        return user;
    }

    /**
     * 根据用户ID修改用户信息
     */
    @Override
    public synchronized void updateUserByuId(User user) {
        SQLiteDatabase db = dbHelper.openDatabase(); // 获取一个可写的数据库
        String sql = "update t_user set u_phone=? ,u_realname=?"
                + ", u_sex=? ,u_height=? ,u_weight=? ,u_birthday=?, u_domicile=?"
                + ", u_email=? ,u_weibo=? where u_id = ?";
        db.execSQL(sql, new Object[]{user.getuPhone(), user.getuRealName(), user.getuSex(),
                user.getuHeight(), user.getuWeight(), user.getuBirthday(),
                user.getuDomicile(), user.getuEmail(), user.getuWeibo(), user.getuId()});
        dbHelper.closeDatabase();
    }

    /**
     * 插入用户信息
     */
    @Override
    public synchronized void insertUser(User user) {
        SQLiteDatabase db = dbHelper.openDatabase(); // 获取一个可写的数据库
        String sql = "insert into t_user(u_id, u_phone,  u_realname"
                + ", u_sex ,u_height ,u_weight ,u_birthday"
                + ", u_domicile, u_email ,u_weibo)"
                + "values(?,?,?,?,?,?,?,?,?,?)";
        db.execSQL(sql, new Object[]{user.getuId(), user.getuPhone(), user.getuRealName(),
                user.getuSex(), user.getuHeight(), user.getuWeight(),
                user.getuBirthday(), user.getuDomicile(), user.getuEmail(), user.getuWeibo()});
        dbHelper.closeDatabase();
    }

    /**
     * 根据用户ID删除用户ID
     *
     * @param uId 用户ID
     */
    @Override
    public synchronized void deleteUserByUid(long uId) {
        SQLiteDatabase db = dbHelper.openDatabase(); // 获取一个可写的数据库
        String sql = "delete from t_user where u_id=?";
        db.execSQL(sql, new Long[]{uId});
        dbHelper.closeDatabase();
    }
}

最后使用

SQLiteDaoImpl sqLiteDao = new SQLiteDaoImpl(this);
List<User> users = sqLiteDao.selectUser();

GitHub地址
阅读原文

《【Android】数据存储全方案之SQLite初体验》 微信公众号:书客创作

    原文作者:吾非言
    原文地址: https://www.jianshu.com/p/baddfd8f80f0
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞