Android SQLite 数据库

用习惯了三方数据库,原生的 SQLite 数据库是不是有一些陌生了?而且什么时候 create,什么时候需要 upgrade 是不是也有些记不清了?是不是有时还会不小心用出了 no such table 的异常?那就一起来看一看吧!

  • 数据库的使用
    1.extends SQLiteOpenHelper;
    2.构造方法传入数据库的库名和版本号;
    3.实现方法 onCreate(SQLiteDatabase db)以及 onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);
public class DataBaseHelper extends SQLiteOpenHelper {
    /**
     * 数据库名称
     */
    static final String DATABASE_NAME = "DBName.db";
    /**
     * 数据库版本号
     */
    static final int VERSION = 1;

    /**
     * 构造方法
     */
    private DataBaseHelper(Context context) {
        super(context, DATABASE_NAME, null, VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}
  • 跟着源码看流程
    数据库的流程(建库,onCreate,onUpgrade,建表时机)
    通过构造方法设置初始值,比较重要的参数是: 1.库名,2.版本号
//最终会调用此方法
private SQLiteOpenHelper(@Nullable Context context, @Nullable String name, int version,
            int minimumSupportedVersion,
            @NonNull SQLiteDatabase.OpenParams.Builder openParamsBuilder) {
        Preconditions.checkNotNull(openParamsBuilder);
        //判断版本号,数据库的版本号必须大于1
        if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);
        //进行初始赋值
        mContext = context;
        mName = name;
        mNewVersion = version;
        mMinimumSupportedVersion = Math.max(0, minimumSupportedVersion);
        setOpenParamsBuilder(openParamsBuilder);
}

首次调用 getWritableDatabase()或 getReadableDatabase()时,通过 getDatabaseLocked(boolean writable)建立数据库,在这里进行完毕的时候,我们完成了建库
而我们一般会选择在 onCreate(db);当中进行建表

public SQLiteDatabase getWritableDatabase() {
    synchronized (this) {
      return getDatabaseLocked(true);
    }
}

public SQLiteDatabase getReadableDatabase() {
    synchronized (this) {
      return getDatabaseLocked(false);
    }
}

private SQLiteDatabase getDatabaseLocked(boolean writable) {
    ...
    //version首次进入的时候,version = 0;
    final int version = db.getVersion();
            //mNewVersion是在构造函数中赋值,且不可小于1,则在首次进入时,是一定会满足条件的
            if (version != mNewVersion) {
                if (db.isReadOnly()) {
                    throw new SQLiteException("Can't upgrade read-only database from version " +
                            db.getVersion() + " to " + mNewVersion + ": " + mName);
                }

                if (version > 0 && version < mMinimumSupportedVersion) {
                    ...
                } else {
                    //我们并没有设置mMinimumSupportedVersion,因此会进入这里
                    //开启一个事务,只有建库的过程全部完成,才算成功,否则,都不算做成功
                    db.beginTransaction();
                    try {
                        //这里又看到了version,当手机当中没有建立数据库时(以我们在构造方法中指定的库名为准),version是为0的,当已经建立过
                        //数据库的时候,这个值就不再是0了
                        if (version == 0) {
                            //则会进行创建,也就是我们需要实现的方法,这也就是常说的,为什么只有在没有库的时候才会走onCreate
                            //,而其余的情况都不会走了
                            onCreate(db);
                        } else {
                            //可以看到,是两种情况,version和构造方法当中传入的mNewVersion相比较
                            //如果mNewVersion比较小,则证明你的版本比之前记录的版本低了,因此会进行降级,我们一般使用的比较少
                            if (version > mNewVersion) {
                                onDowngrade(db, version, mNewVersion);
                            } else {
                                //如果mNewVersion比较大,则找到了onUpgrade,这个我们可以实现用来进行自己操作的方法
                                onUpgrade(db, version, mNewVersion);
                            }
                            //看到这里,是不是有一些好奇,相等的情况哪里去了,哈哈,看一下最上面if (version != mNewVersion),如果
                            version == mNewVersion,则这些都根本都不会进入
                        }
                        db.setVersion(mNewVersion);
                        db.setTransactionSuccessful();
                    } finally {
                        db.endTransaction();
                    }
                }
            }
           ...
        } finally {
          ...
        }
    }
  • 建表
    1.一般情况下,我们是在 onCreate(db);中进行数据表的创建的,跟随数据库一起创建
    2.当数据库已经存在,而我们希望再新建一张新表的时候,从上面的分析已经知道,不会再重走 onCreate(db);了,这个时候,需要更改数据库的版本号,通过 onUpgrade(db, version, mNewVersion);处进行建表
    3.这个时候,数据库的名字已经知道了,想要建立一张表,就需要 (1.数据表的名称;2.每一列的列名,3.指定列名的同时,需要指定列的类型)
id 列 0 列 1 列 2
1 列 0 数据 列 1 数据 列 2 数据
2 列 0 数据 列 1 数据 列 2 数据
3 列 0 数据 列 1 数据 列 2 数据
4 列 0 数据 列 1 数据 列 2 数据

示例

/**
 * 表名
 */
static final String DATABASE_NAME = "TABLE_NAME.db";
/**
 * 列名
 */
private final static String USER_NAME = "USER_NAME";
private final static String USER_PSW = "USER_PSW";

在这里,我们可能需要一点小小的帮助:
public static final String create = "CREATE TABLE IF NOT EXISTS ";
public static final String id = BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, ";

//UserDataDao
public static final String CREATE_TABLE_SQL = provideCreateTableSql();

private static String provideCreateTableSql() {
        return DBSQL.create + TABLE_NAME + " (" +
                DBSQL.id +
                USER_NAME + " TEXT," +
                USER_PSW + " TEXT);";
}
//完整的sql语句 TEXT指明的是列当中的数据类型均为String
//当然,如果有多个列,那就照样子添加就可以了
CREATE TABLE IF NOT EXISTS USER_TABLE (_id INTEGER PRIMARY KEY AUTOINCREMENT, USER_NAME TEXT,USER_PSW TEXT);

//这个时候,我们来修改一下onCreate(db);当中的代码
@Override
public void onCreate(SQLiteDatabase db) {
    createTable(db, UserDataDao.CREATE_TABLE_SQL);
}

//因为我们可能创建多张表,用一个方法表示一下,每多一张表,就多添加一遍就可以,参数就是上面所介绍的SQL语句
private synchronized void createTable(SQLiteDatabase db, String createTableSQL) {
        try {
            db.execSQL(createTableSQL);
        } catch (Exception ignored) {

        }
}
  • 增删改查
//增 put键值对就可以了
public synchronized void insert(UserBean userBean) {
    try {
      ContentValues contentValues = new ContentValues();
      contentValues.put(USER_NAME, userBean.mUserName);
      contentValues.put(USER_PSW, userBean.mUserPsw);
      mDbHelper.getWritableDatabase().insert(TABLE_NAME, null, contentValues);
    } catch (Exception ignored) {

    }
}

//删
//根据列中的值删除
//参数 1.表名;2.列名 + "=?";3.所根据的列的值
public synchronized void delete(UserBean userBean) {
    try {
      mDbHelper.getWritableDatabase().delete(TABLE_NAME
              , USER_NAME + "=?"
              , new String[]{userBean.mUserName});
    } catch (Exception ignored) {

    }
}

//改
//根据列中的值更改
//columnsToUpdata列中原来的值
//和insert一样,先制作一个需要插入的数据
//参数 1.表名;2,制作的需要插入的数据,3.列名 + "=?";4.列中原来的值
public synchronized void upData(UserBean userBean,String columnsToUpdata) {
        try {
            ContentValues contentValues = new ContentValues();
            contentValues.put(USER_NAME, userBean.mUserName);
            contentValues.put(USER_PSW, userBean.mUserPsw);
            mDbHelper.getWritableDatabase().update(TABLE_NAME,contentValues
                    , USER_NAME + "=?"
                    , new String[]{columnsToUpdata});
        } catch (Exception ignored) {

        }
}

//查 查询表中全部数据
public static final String queryAll = "SELECT * FROM ";
private static final String SQL_QUERY_ALL = DBSQL.queryAll + TABLE_NAME;

public synchronized List queryAll() {
        List list = new ArrayList<>();
        try {
            Cursor cursor = mDbHelper.getWritableDatabase().rawQuery(SQL_QUERY_ALL, new String[]{});
            while (cursor.moveToNext()) {
                String name = cursor.getString(cursor.getColumnIndex(USER_NAME));
                String psw = cursor.getString(cursor.getColumnIndex(USER_PSW));
                UserBean userBean = new UserBean();
                userBean.mUserName = name;
                userBean.mUserPsw = psw;
                list.add(userBean);
            }
            cursor.close();
        } catch (Exception ignored) {

        }
        return list;
}

//查 根据指定列的值查询
private static final String SQL_QUERY_BY_COLUMS_VALUE = "SELECT * FROM " + TABLE_NAME + " WHERE " + USER_NAME + " = ?";
 public synchronized List getByColumnsValue(String value) {
 List list = new ArrayList<>();
        try {
            Cursor cursor = mDbHelper.getWritableDatabase().rawQuery(SQL_QUERY_BY_COLUMS_VALUE , new String[]{value});
            while (cursor.moveToNext()) {
                String name = cursor.getString(cursor.getColumnIndex(USER_NAME));
                String psw = cursor.getString(cursor.getColumnIndex(USER_PSW));
                UserBean userBean = new UserBean();
                userBean.mUserName = name;
                userBean.mUserPsw = psw;
                list.add(userBean);
            }
            cursor.close();
        } catch (Exception ignored) {

        }
        return list;
    }

//删除表
public static final String drop = "DROP TABLE IF EXISTS ";
private static final String DELETE_TABLE = DBSQL.drop + TABLE_NAME;

public synchronized void deleteTable() {
  try {
    mDbHelper.getWritableDatabase().execSQL(DELETE_TABLE);
  } catch (Exception ignored) {

  }
}

你可能感兴趣的:(Android SQLite 数据库)