Android之 常用数据库框架整理

您所在的位置:网站首页 安卓好用的框架 Android之 常用数据库框架整理

Android之 常用数据库框架整理

2024-04-07 21:06| 来源: 网络整理| 查看: 265

一 简介

1.1 上节说了关系型数据库有以下几种:

Oracle、Microsoft SQL Server、Microsoft Access、MySQL、SQLite

1.2 各自的领域也不一样

java,C#,php等用Oracle,Microsoft SQL Server,MySQL比较多。

移动端Android,IOS等用SQLite比较多

1.3 SQLite是一种轻量型数据库,有以下优点:

不需要一个单独的服务器进程或操作的系统(无服务器的)。

SQLite 不需要配置,这意味着不需要安装或管理。

一个完整的 SQLite 数据库是存储在一个单一的跨平台的磁盘文件。

SQLite 是非常小的,是轻量级的,完全配置时小于 400KiB,省略可选功能配置时小于250KiB。

SQLite 是自给自足的,这意味着不需要任何外部的依赖。

SQLite 事务是完全兼容 ACID 的,允许从多个进程或线程安全访问。

SQLite 支持 SQL92(SQL2)标准的大多数查询语言的功能。

SQLite 使用 ANSI-C 编写的,并提供了简单和易于使用的 API。

SQLite 可在 UNIX(Linux, Mac OS-X, Android, iOS)和 Windows(Win32, WinCE, WinRT)中运行。

二 Android 本地数据库框架 

2.1 android数据库框架有Room,Relam,GreenDAO,ObjectBox,SQLDelight等等。

2.2 常用的有Room,GreenDAO等,在前两个没出现之前主要用的Android官方原生框架SQLiteOpenHelper。

三 SQLiteOpenHelper 框架的使用

3.1 SQLiteOpenHelper是官方api,因此不需要引入其它库。如下可以看到,SQLiteOpenHelper在android.database.sqlite包下面

 3.2 SQLiteOpenHelper的使用,自定义DatabaseHelper,继承SQLiteOpenHelper,来管理数据库的创建和数据库表的创建

public class DatabaseHelper extends SQLiteOpenHelper { public static final String DATABASE_NAME = "SMSManager.db";//数据库名字 private static final int DATABASE_VERSION = 1; // 数据库的版本号 public static final String CONTACTS_TABLE_NAME = "contacts_table";//联系人表名 //创建联系人表SQL语句 public static final String CREATE_CONTACTS_TABLE = "create table " + CONTACTS_TABLE_NAME + "(" + "cid integer primary key autoincrement," + "sendPhone varchar(50),name varchar(50) not null," + "phone varchar(50) not null" + ")"; /** * DatabaseHelper构造函数,传参数据库名,数据库版本,会自动创建数据库 * @param context */ public DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } /** * onCreate 回调SQLiteDatabase对象,自动执行创建表语句 * @param db */ @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_CONTACTS_TABLE); } /** * 升级数据库。执行表结构变更语句 * @param db * @param oldVersion * @param newVersion */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // if (newVersion > 1) { // //Android的ALTER命令不支持一次添加多列,只能分多次添加 // String alter_sql = "ALTER TABLE " + CONTACTS_TABLE_NAME + " ADD COLUMN " + "phone_new2 VARCHAR;"; // db.execSQL(alter_sql); // alter_sql = "ALTER TABLE " + CONTACTS_TABLE_NAME + " ADD COLUMN " + "phone_new3 VARCHAR;"; // db.execSQL(alter_sql); // 执行完整的SQL语句 // } } }

3.3 创建联系人表的实体类ContactsInfo

public class ContactsInfo implements Serializable{ int cid; String name; String phone; String sendPhone; boolean isChoosed=false; public int getCid() { return cid; } public void setCid(int cid) { this.cid = cid; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getSendPhone() { return sendPhone; } public void setSendPhone(String sendPhone) { this.sendPhone = sendPhone; } public boolean isChoosed() { return isChoosed; } public void setChoosed(boolean choosed) { isChoosed = choosed; } }

3.4 创建联系人表的管理类ContactsDatabase,进行表的增删改查操作

public class ContactsDatabase { private final DatabaseHelper dbHelper; public ContactsDatabase(Context context) { super(); dbHelper = new DatabaseHelper(context); } /** * 增 * * @param data */ public void insert(ContactsInfo data) { String sql = "insert into " + DatabaseHelper.CONTACTS_TABLE_NAME; sql += "(sendPhone, name, phone) values(?,?,?)"; SQLiteDatabase sqlite = dbHelper.getWritableDatabase(); sqlite.execSQL(sql, new String[] {data.getSendPhone() + "",data.getName() + "", data.getPhone() + ""}); sqlite.close(); } /** * 删 * * @param where */ public void delete(String where) { SQLiteDatabase sqlite = dbHelper.getWritableDatabase(); String sql = "delete from " + DatabaseHelper.CONTACTS_TABLE_NAME + where; sqlite.execSQL(sql); sqlite.close(); } /** * 改 * * @param data */ public void update(ContactsInfo data) { SQLiteDatabase sqlite = dbHelper.getWritableDatabase(); String sql = ("update " + DatabaseHelper.CONTACTS_TABLE_NAME +" set sendPhone=?,name=?,phone=? where cid=?"); sqlite.execSQL(sql, new String[] { data.getSendPhone() + "", data.getName() + "", data.getPhone()+ "", data.getCid()+ ""}); sqlite.close(); } /** * 查一条数据 * * @param where * @return */ public ContactsInfo queryContactsInfo(String where) { ContactsInfo contactsInfo = null; SQLiteDatabase sqlite = dbHelper.getReadableDatabase(); String sql= "select * from " + DatabaseHelper.CONTACTS_TABLE_NAME + where; Cursor cursor = sqlite.rawQuery(sql, null); for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { contactsInfo= new ContactsInfo(); contactsInfo.setCid(cursor.getInt(0)); contactsInfo.setSendPhone(cursor.getString(1)); contactsInfo.setName(cursor.getString(2)); contactsInfo.setPhone(cursor.getString(3)); } if (!cursor.isClosed()) { cursor.close(); } sqlite.close(); return contactsInfo; } /** * 查 * * @param where * @return */ public List query(String where) { SQLiteDatabase sqlite = dbHelper.getReadableDatabase(); ArrayList data = null; data = new ArrayList(); String sql="select * from " + DatabaseHelper.CONTACTS_TABLE_NAME + where; Cursor cursor = sqlite.rawQuery(sql, null); for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { ContactsInfo contactsInfo = new ContactsInfo(); contactsInfo.setSendPhone(cursor.getString(1)); contactsInfo.setName(cursor.getString(2)); contactsInfo.setPhone(cursor.getString(3)); data.add(contactsInfo); } if (!cursor.isClosed()) { cursor.close(); } sqlite.close(); return data; } /** * 查 * * @param where * @return */ public int queryCount(String where) { SQLiteDatabase sqlite = dbHelper.getReadableDatabase(); String sql="select count(*) from " + DatabaseHelper.CONTACTS_TABLE_NAME+where ; Cursor cursor = sqlite.rawQuery(sql, null); cursor.moveToFirst(); int count = cursor.getInt(0); sqlite.close(); return count; } /** * 重置 * * @param datas */ public void reset(List datas) { if (datas != null) { SQLiteDatabase sqlite = dbHelper.getWritableDatabase(); // 删除全部 sqlite.execSQL("delete from " + DatabaseHelper.CONTACTS_TABLE_NAME); // 重新添加 for (ContactsInfo data : datas) { insert(data); } sqlite.close(); } } public void destroy() { dbHelper.close(); } }

3.5 总结:

第一步:SQLiteOpenHelper的构造函数创建数据库

public DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, 1); }

第二步:SQLiteOpenHelper的onCreate里面执行创建表的sql语句

@Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_CONTACTS_TABLE); }

第三步:获取当前数据库对象实例,打开数据库,进行增删改查操作

SQLiteDatabase sqlite = dbHelper.getWritableDatabase(); sqlite .insert(TABLE_NAME, "",entity); sqlite .delete(TABLE_NAME, entity, null); sqlite .update(TABLE_NAME, entity, "name=?", new String[]{info.name}); sqlite .rawQuery(sql, null);

第四步:关闭数据库

if (sqlite != null && sqlite .isOpen()) {     sqlite .close();     sqlite = null; }

四 GreenDAO 框架的使用

4.1 GreenDAO 是一种轻量级快速ORM 框架,可将对象映射到 SQLite 数据库中

4.2 ORM 框架,即 Object-Relational Mapping,它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体操作数据库的时候,就不需要再去和复杂的 SQL 语句打交道,只是像平时操作对象一样操作它就可以了

在这里插入图片描述

 4.3 GreenDAO主要类介绍

DaoMaster:DaoMaster保存数据库对象(SQLiteDatabase)并管理特定模式的DAO类(而不是对象)。它有静态方法来创建表或删除它们。它的内部类OpenHelper和DevOpenHelper是SQLiteOpenHelper实现,它们在SQLite数据库中创建模式。DaoSession:管理特定模式的所有可用DAO对象,您可以使用其中一个getter方法获取该对象。DaoSession还提供了一些通用的持久性方法,如实体的插入,加载,更新,刷新和删除。DAO:数据访问对象(DAO)持久存在并查询实体。对于每个实体,greenDAO生成实体XXDAO。它具有比DaoSession更多的持久性方法,例如:count,loadAll和insert等。Entities :可持久化对象。通常, 实体对象代表一个数据库行使用标准 Java 属性(如一个POJO 或 JavaBean )。

4.4 GreenDAO的使用

工程目录build.gradle里面引入greenDao的插件

dependencies { classpath "com.android.tools.build:gradle:7.0.0" classpath 'org.greenrobot:greendao-gradle-plugin:3.3.0' }

app的build.gradle里面使用插件,配置数据库,并引入greenDao的依赖库

plugins { id 'com.android.application' id 'org.greenrobot.greendao' } android { compileSdk 32 defaultConfig { applicationId "com.greendao.demo" minSdk 21 targetSdk 32 versionCode 1 versionName "1.0" } } greendao { //指定数据库schema版本号,迁移等操作会用到 schemaVersion 1 //设置生成数据库文件的目录,默认是在build中,可以将生成的文件放到我们的java目录中 targetGenDir 'src/main/java' //设置生成的数据库相关文件的包名,默认为entity所在的包名 daoPackage 'com.greendao.demo.greendao.database' } dependencies { implementation 'org.greenrobot:greendao:3.3.0' }

4.5 封装数据库管理器DaoManager,用来创建数据库、创建数据库表、包含增删改查的操作以及数据库的升级

/** * 创建数据库、创建数据库表、包含增删改查的操作以及数据库的升级 */ public class DaoManager { private static final String TAG = DaoManager.class.getSimpleName(); private static final String DB_NAME = "diary.db"; private Context context; //多线程中要被共享的使用volatile关键字修饰 private volatile static DaoManager manager ; private static DaoMaster sDaoMaster; private static DaoMaster.DevOpenHelper sHelper; private static DaoSession sDaoSession; /** * 单例模式获得操作数据库对象 * * @return */ public static DaoManager getInstance() { synchronized (DaoManager.class) { if (manager == null) { manager = new DaoManager(); } } return manager; } private DaoManager() { setDebug(); } public void init(Context context) { this.context = context; } /** * 判断是否有存在数据库,如果没有则创建 * * @return */ public DaoMaster getDaoMaster() { if (sDaoMaster == null) { sHelper = new DaoMaster.DevOpenHelper(context, DB_NAME, null); sDaoMaster = new DaoMaster(sHelper.getWritableDatabase()); } return sDaoMaster; } /** * 完成对数据库的添加、删除、修改、查询操作,仅仅是一个接口 * * @return */ public DaoSession getDaoSession() { if (sDaoSession == null) { if (sDaoMaster == null) { sDaoMaster = getDaoMaster(); } sDaoSession = sDaoMaster.newSession(); } return sDaoSession; } /** * 打开输出日志,默认关闭 */ public void setDebug() { if (BuildConfig.DEBUG) { QueryBuilder.LOG_SQL = true; QueryBuilder.LOG_VALUES = true; } } /** * 关闭所有的操作,数据库开启后,使用完毕要关闭 */ public void closeConnection() { closeHelper(); closeDaoSession(); } public void closeHelper() { if (sHelper != null) { sHelper.close(); sHelper = null; } } public void closeDaoSession() { if (sDaoSession != null) { sDaoSession.clear(); sDaoSession = null; } } }

4.6 在项目Application里面初始化GreenDAO

DaoManager.getInstance().init(this);

4.7 以Uer表为例,创建一个User实体类。实体类开头必须加 @Entity 注解

@Entity public class User { @Id(autoincrement = true) Long id; String account; String password; String name="tom"; String avatar; int gender=0; String mobile; @Generated(hash = 998056223) public User(Long id, String account, String password, String name, String avatar, int gender, String mobile) { this.id = id; this.account = account; this.password = password; this.name = name; this.avatar = avatar; this.gender = gender; this.mobile = mobile; } }

编译后User实体类目会自动生成GET,SET方法

@Entity public class User { @Id(autoincrement = true) Long id; String account; String password; String name="tom"; String avatar; int gender=0; String mobile; @Generated(hash = 998056223) public User(Long id, String account, String password, String name, String avatar, int gender, String mobile) { this.id = id; this.account = account; this.password = password; this.name = name; this.avatar = avatar; this.gender = gender; this.mobile = mobile; } @Generated(hash = 586692638) public User() { } public Long getId() { return this.id; } public void setId(Long id) { this.id = id; } public String getAccount() { return this.account; } public void setAccount(String account) { this.account = account; } public String getPassword() { return this.password; } public void setPassword(String password) { this.password = password; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public String getAvatar() { return this.avatar; } public void setAvatar(String avatar) { this.avatar = avatar; } public int getGender() { return this.gender; } public void setGender(int gender) { this.gender = gender; } public String getMobile() { return this.mobile; } public void setMobile(String mobile) { this.mobile = mobile; } }

同时编译后还会在 build 目录下生成XXXDao实体类,通过DAO实体就能操作数据库了

 4.7 可以封装一个通用的增删改查工具类,这样像正常操作对象那样就可以了

/** * 通用greendao工具 * @param */ public class CommonDaoUtils { private static final String TAG = CommonDaoUtils.class.getSimpleName(); private DaoSession daoSession; private Class entityClass; private AbstractDao entityDao; public CommonDaoUtils(Class pEntityClass, AbstractDao pEntityDao) { DaoManager mManager = DaoManager.getInstance(); daoSession = mManager.getDaoSession(); entityClass = pEntityClass; entityDao = pEntityDao; } public DaoSession getDaoSession() { return daoSession; } /** * 插入记录,如果表未创建,先创建表 * * @param pEntity * @return */ public boolean insert(T pEntity) { boolean flag = entityDao.insert(pEntity) == -1 ? false : true; return flag; } /** * 插入记录数据存在则替换,数据不存在则插入 * * @param pEntity * @return */ public boolean insertOrReplace(T pEntity) { boolean flag = entityDao.insertOrReplace(pEntity) == -1 ? false : true; return flag; } /** * 插入多条数据,在子线程操作 * * @param pEntityList * @return */ public boolean insertMulti(final List pEntityList) { try { daoSession.runInTx(new Runnable() { @Override public void run() { for (T meizi : pEntityList) { daoSession.insertOrReplace(meizi); } } }); return true; } catch (Exception e) { e.printStackTrace(); } return false; } /** * 修改一条数据 * * @param pEntity * @return */ public boolean update(T pEntity) { try { daoSession.update(pEntity); return true; } catch (Exception e) { e.printStackTrace(); } return false; } /** * 删除单条记录 * * @param pEntity * @return */ public boolean delete(T pEntity) { try { //按照id删除 daoSession.delete(pEntity); return true; } catch (Exception e) { e.printStackTrace(); } return false; } /** * 删除所有记录 * * @return */ public boolean deleteAll() { try { //按照id删除 daoSession.deleteAll(entityClass); return true; } catch (Exception e) { e.printStackTrace(); } return false; } /** * 查询所有记录 * * @return */ public List queryAll() { return daoSession.loadAll(entityClass); } /** * 根据主键id查询记录 * * @param key * @return */ public T queryById(long key) { return daoSession.load(entityClass, key); } /** * 使用native sql进行查询操作 */ public List queryByNativeSql(String sql, String[] conditions) { return daoSession.queryRaw(entityClass, sql, conditions); } /** * 使用queryBuilder进行查询 * * @return */ public List queryByQueryBuilder(WhereCondition cond, WhereCondition... condMore) { QueryBuilder queryBuilder = daoSession.queryBuilder(entityClass); return queryBuilder.where(cond, condMore).list(); } /** * 使用queryBuilder进行查询 * * @return */ public List queryByBuilder(WhereCondition cond) { QueryBuilder queryBuilder = daoSession.queryBuilder(entityClass); return queryBuilder.where(cond).list(); } }

4.8 再定义具体的Dao操作类,实现单独管理

public class DaoUserUtils { private volatile static DaoUserUtils instance; public CommonDaoUtils userCommonDaoUtils; public static DaoUserUtils getInstance() { synchronized (DaoUserUtils.class) { if(instance==null){ instance = new DaoUserUtils(); } } return instance; } private DaoUserUtils() { DaoManager mManager = DaoManager.getInstance(); userCommonDaoUtils = new CommonDaoUtils(User.class,mManager.getDaoSession().getUserDao()); } //新建用户 public void daoInsertDefaultUser(){ String account="boss1"; String password="123456"; if(daoQueryAllUser().size()==0){ User user= new User(); user.setAccount(account); user.setPassword(password); userCommonDaoUtils.insert(user); } } //查询用户 public List daoQueryAllUser(){ return userCommonDaoUtils.queryAll(); } //查询用户 public User daoQueryUser(long id){ return userCommonDaoUtils.queryById(id); } //删除用户 public boolean deleteAllUser(){ return userCommonDaoUtils.deleteAll(); } //更新用户 public boolean updateUser(User user){ return userCommonDaoUtils.update(user); } }

4.9 GreenDao提供有丰富的操作数据库接口,比如查询常用的三种方式:

load(entityClass, dataKey); 主键查询单条数据loadAll():查询所有数据。queryRaw():根据条件查询。queryBuilder() : 方便查询的创建,后面详细讲解。

而且queryBuilder功能非常强大,比如下面常见的方法:

where(WhereCondition cond, WhereCondition... condMore): 查询条件,参数为查询的条件!or(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore): 嵌套条件或者,用法同or。and(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore): 嵌套条件且,用法同and。join(Property sourceProperty, Class destinationEntityClass):多表查询,后面会讲。 输出结果有四种方式,选择其中一种最适合的即可,list()返回值是List,而其他三种返回值均实现Closeable,需要注意的不使用数据时游标的关闭操作:list ()所有实体都加载到内存中。结果通常是一个没有魔法的 ArrayList。最容易使用。listLazy ()实体按需加载到内存中。首次访问列表中的元素后,将加载并缓存该元素以供将来使用。必须关闭。listLazyUncached ()实体的“虚拟”列表:对列表元素的任何访问都会导致从数据库加载其数据。必须关闭。listIterator ()让我们通过按需加载数据(懒惰)来迭代结果。数据未缓存。必须关闭。orderAsc() 按某个属性升序排;orderDesc() 按某个属性降序排;

以及Property中丰富的查询函数:

eq():"equal ('=?')" 等于;notEq() :"not equal ('?')" 不等于;like():" LIKE ?" 值等于;between():" BETWEEN ? AND ?" 取中间范围;in():" IN (" in命令;notIn():" NOT IN (" not in 命令;gt():">?" 大于;lt():"


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3