Android 数据库框架 LiteOrm使用

2024-02-05 03:48

本文主要是介绍Android 数据库框架 LiteOrm使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

版权声明:转载请注明出处 https://github.com/baiiu

 

前言

关于Android ORM框架,之前写过关于GreenDao的使用,在被安利了一篇 Android数据库框架:greenDAO vs LiteOrm ,又看了下LiteOrm的基本使用,很方便,而且效率并不低,特别是在级联查询上,很方便很面向对象。

恩,LiteOrm不是OrmLite。关于它的使用主要是看GitHub上的samples,因为它没有文档。不过数据库框架的使用方法都比较相似,看看方法名大概就能猜出来什么意思。

GitHub地址:https://github.com/litesuits/android-lite-orm 
LiteSuits 官网: http://litesuits.com/?form=gorm

1. 开始使用

/*
1. 创建config信息
*/
DataBaseConfig config = new DataBaseConfig(mContext);
//数据库名,可设置存储路径。默认在内部存储位置databases文件夹下
config.dbName = DB_NAME_PATH + File.separator + DB_NAME;
config.debugged = true; //是否打Log
config.dbVersion = 1; // database Version
config.onUpdateListener = null; //升级/*
2. 生成实例对象
*/
//级联操作
liteOrm = LiteOrm.newCascadeInstance(config);
//独立操作
liteOrm = LiteOrm.newSingleInstance(config);

可以看到,LiteOrm提供了两种获取实例的方式:singleInstance和cascadeInstance。其中:

    独立操作:使用 LiteOrm 的 single 实例,可与 cascade 方式平滑切换,性能高,仅处理该对象数据,其关系、和关联对象忽略;级联操作:使用 LiteOrm 的 cascade 实例,可与 single 方式平滑切换,全递归,该对象数据,及其关系、和关联对象都被处理;

这两种获取方式根据项目需求而定,如果级联操作比较多的话,就可以使用cascadeInstance,而其又可以和独立操作任意切换:

LiteOrm db = LiteOrm.newCascadeInstance(this, "cascade.db");
db.cascade().save(user);//级联操作:保存[当前对象],以及该对象所有的[关联对象]以及它们的[映射关系]。
db.single().save(user);//非级联操作:仅保存[当前对象],高效率。

从此处就可以看到该框架的强大了吧。最简单的是它通过注解的形式声明对象间关系,那下面就说说它的注解。

2. 注解

基础注解

  • @Table("test_model") 表名
  • @PrimaryKey(AssignType.AUTO_INCREMENT) 主键自增长
  • @PrimaryKey(AssignType.BY_MYSELF) 自己设置主键
  • @Ignore 忽略该字段,不存入数据库
  • @Column("login") 指定列名
  • @Collate("NOCASE") 大小写无关

关系映射:

  • @Mapping(Relation.ManyToMany) 多对多
  • @Mapping(Relation.OneToMany) 一对多
  • @Mapping(Relation.OneToOne) 一对一
  • @Mapping(Relation.ManyToOne) 多对一
  • @MapCollection(ConcurrentLinkedQueue.class) 指定约束对象的集合类型

约束相关:

  • @NotNull 非空约束
  • @Default("true") 默认约束
  • @Check("index > 0 ") check约束
  • @Unique 唯一约束
  • @UniqueCombine() 联合唯一约束

约束冲突:

ON CONFLICT 子句不是一个单独的 SQL 命令。 它可以出现在很多其它的 SQL 命令中,是一个非标准的子句。ON CONFLICT 子句指定一个用于解决约束冲突的算法。 有五种选择(具体解释请看文末参考链接,copy过来也没啥意思): 
@Conflict(Strategy.ROLLBACK) 
@Conflict(Strategy.ABORT) 
@Conflict(Strategy.FAIL) 
@Conflict(Strategy.IGNORE) 
@Conflict(Strategy.REPLACE)

这里总结了LiteOrm使用的几乎所有的注解,全部从samples中总结出来。有些一看就懂,但有些就比较生疏。但框架毕竟是框架,用着用着就熟悉了。从注解也可以看出来该框架确实比较全面。为了弄懂一些东西,又复习了一遍Sql语句。因为它的查询某些语法完全和SQL语句一样。下面就介绍一下他的基本CRUD操作。

3. CRUD 操作

常用操作:


- 保存(插入or更新)
School school = new School("hello");
liteOrm.save(school);
- 插入
Book book = new Book("good");
liteOrm.insert(book, ConflictAlgorithm.Abort);
- 更新
book.setIndex(1988);
book.setAuthor("hehe");
liteOrm.update(book);
- 更新指定列
// 把所有书的author强制批量改为liter
HashMap<String, Object> bookIdMap = new HashMap<String, Object>();
bookIdMap.put(Book.COL_AUTHOR, "liter");
liteOrm.update(bookList, new ColumnsValue(bookIdMap), ConflictAlgorithm.Fail);
// 仅 author 这一列更新为该对象的最新值。
//liteOrm.update(bookList, new ColumnsValue(new String[]{Book.COL_AUTHOR}, null), ConflictAlgorithm.Fail);
- 查询
List list = liteOrm.query(Book.class);
OrmLog.i(TAG, list);
- 查找 使用QueryBuilder
List<Student> list = liteOrm.query(new QueryBuilder<Student>(Student.class).where(Person.COL_NAME + " LIKE ?", new String[]{"%0"}).whereAppendAnd().whereAppend(Person.COL_NAME + " LIKE ?", new String[]{"%s%"}));
OrmLog.i(TAG, list);
- 查询 根据ID
Student student = liteOrm.queryById(student1.getId(), Student.class);
OrmLog.i(TAG, student);
- 查询 任意
List<Book> books = liteOrm.query(new QueryBuilder<Book>(Book.class).columns(new String[]{"id", "author", Book.COL_INDEX}).distinct(true).whereGreaterThan("id", 0).whereAppendAnd().whereLessThan("id", 10000).limit(6, 9).appendOrderAscBy(Book.COL_INDEX));
OrmLog.i(TAG, books);
- 删除 实体
// 删除 student-0
liteOrm.delete(student0);
- 删除 指定数量
// 按id升序,删除[2, size-1],结果:仅保留第一个和最后一个
// 最后一个参数可为null,默认按 id 升序排列
liteOrm.delete(Book.class, 2, bookList.size() - 1, "id");
- 删除 使用WhereBuilder
// 删除 student-1
liteOrm.delete(new WhereBuilder(Student.class).where(Person.COL_NAME + " LIKE ?", new String[]{"%1%"}).and().greaterThan("id", 0).and().lessThan("id", 10000));
- 删除全部
// 连同其关联的classes,classes关联的其他对象一带删除
liteOrm.deleteAll(School.class);
liteOrm.deleteAll(Book.class);// 顺带测试:连库文件一起删掉
liteOrm.deleteDatabase();
// 顺带测试:然后重建一个新库
liteOrm.openOrCreateDatabase();
// 满血复活

常用注解:

@Table("class")指定表名是class

@Ignore 忽略字段不被保存到数据库中

@Column("_id") 标明字段在数据中的列名是_id

@Mapping(Relation.XX)用于多表映射

@Check("check > 99")//大于99才存储
private int check = 100;

@Collate("NOCASE") 排序规则,nocase就是大小写无关
private String _collate;

@Default("SQL默认值") 指定字段缺省值

@NotNull 字段不能为空

@PrimaryKey(AssignType.AUTO_INCREMENT) 主键自增长

@Conflict(Strategy.FAIL) 冲突的时候不存储

@Unique 唯一,确保某列中的所有值是不同的。

@UniqueCombine(1) UniqueCombine 值为1,和 UniqueCombine同值 的属性联合唯一
private int mIndex;
@UniqueCombine(1) UniqueCombine值为1,和 mIndex联合唯一
private String author;

@Mapping(Relation.ManyToMany)
@MapCollection(ConcurrentLinkedQueue.class) 表示Queue的具体容器是ConcurrentLinkedQueue
private Queue<Student> studentLinkedQueue;

基础操作:

// 1. 保存数据
Person person = new Person("name",23);
liteOrm.save(person); 
List<Person> list = new ArrayList<>();
liteOrm.save(list);// 2. 读取全部数据
List<Person> list = liteOrm.query(Person.class);// 3. 删除全部
liteOrm.deleteAll(Person.class);
liteOrm.deleteDatabase();

查询操作

查询操作里面这个 ? 必不可少,是不是和写sql很像,? 是个占位符。同时SQL并不区分大小写,但关键字建议大写。

//聚合函数count查询,好像只有这一个
long nums = liteOrm.queryCount(Address.class); //查询有多少行//模糊查询
QueryBuilder<Address> qb = new QueryBuilder<Address>(Address.class).where("address LIKE ?", new String[]{"%山%"});//与或非等
qb = new QueryBuilder<Address>(Address.class)        
.whereEquals("city", "南京")
.whereAppendAnd() 
.whereEquals("address", "香港路");//自己拼SQL语句
QueryBuilder<Address> qb = new QueryBuilder<Address>(Address.class)        
.columns(new String[]{Address.COL_ADDRESS})    //查询列
.appendOrderAscBy(Address.COL_ADDRESS)        //升序
.appendOrderDescBy(Address.COL_ID)       //当第一列相同时使用该列降序排序
.distinct(true)        //去重
.where(Address.COL_ADDRESS + "=?", new String[]{"香港路"}); //where条件liteOrm.query(qb);

 

在写查询语句时,一定要铭记sql语句:

SELECTFROMWHERE 条件
GROUP BY 分组条件
HAVING 分组后条件
ORDER BY 排序
LIMIT (x,y)

 

LiteOrm提供的查询功能很强大,看到这是不是和我一样想去把sql复习一遍?毕竟好久没写sql语句了。用框架多了都忘记原理了。 
看了下LiteOrm的query过程,底层确实还是拼sql语句,这样想想realm确实犀利,毕竟自己做的引擎,快是必须的了。下面介绍一下LiteOrm的级联查询,这一块我看到的时候立刻就爱上了它,完完全全的面向对象的操作,表也帮你自动生成。

4. 级联操作

为什么说面向对象呢。就是仅仅需要在JavaBean里声明对象间关系,并用注解标识就OK了。举个例子:

@Table("school")
public class School{@Mapping(Relation.OneToMany)public ArrayList<Classes> classesList; //一个学校有多个教室
}@Table("class")public class Classes  {        @Mapping(Relation.OneToOne)   public Teacher teacher; //一个教室有一个老师,假设
}@Table("teacher")public class Teacher {   @Mapping(Relation.ManyToMany)    @MapCollection(ConcurrentLinkedQueue.class)   private Queue<Student> studentLinkedQueue; //一个老师多个学生,一个学生多个老师,多对多关系
}@Table("student")public class Student  {    @Mapping(Relation.ManyToMany)    private Teacher[] teachersArray;//一个老师多个学生,一个学生多个老师,多对多关系
}

就这样声明,你在Java里创建完对象后使用save()方法保存后,数据库中各种关联表就建好了,完全不用自己设置主键、外键什么的。是不是很方便?不过前提是你要使用LiteOrm.newCascadeInstance(config)这个实例。

说完了这些就该考虑封装啦,因为毕竟数据库框架这种东西没有最好,只有更好。说不定哪一天Square出一个Orm框架也说不定。所以就单独封装一层,方便对外提供方法并且方便以后可能的替换。

5. 基础封装

在上一篇 Retrofit2.0 封装 的封装中使用了枚举来封装,真的不错,很方便,比单例方便而且更安全。所有同样还是使用枚举来封装。

public enum UOrm implements SQLiteHelper.OnUpdateListener {INSTANCE;private LiteOrm mLiteOrm;UOrm() {DataBaseConfig config = new DataBaseConfig(MyApplcation.mContext);config.dbName = DB_NAME_PATH + File.separator + DB_NAME;config.dbVersion = 1;config.onUpdateListener = this;config.debugged = BuildConfig.DEBUG;//可替换为 newCascadeInstance支持级联操作mLiteOrm = LiteOrm.newSingleInstance(config);}@Override public void onUpdate(SQLiteDatabase sqLiteDatabase, int i, int i1) {}public void save(Object o) {if (o == null) {return;}mLiteOrm.save(o);}public <T> void save(List<T> collection) {if (CommonUtil.isEmpty(collection)) {return;}mLiteOrm.save(collection);}public <T> void delete(Class<T> tClass) {if (tClass == null) {return;}mLiteOrm.delete(tClass);}public <T> List<T> queryAll(Class<T> tClass) {if (tClass == null) {return null;}return mLiteOrm.query(tClass);}}

使用时只用这样调用:

    UOrm.INSTANCE.save(modelA);

这里的封装仅仅提供了最最基础的方法,主要是提供liteOrm的实例。你也可以根据业务需求向里面添加方法。 
写到这感觉这样封装并不是很好,如果你有更好的封装方法请告诉我哈,大家一起交流。

结语

关于数据库框架,自己所考虑的主要是性能和方便调用。

Realm性能超级高,但是它对model类限制的太多,直接导致某些情况下model不能复用,需要重新拷贝一份来单独处理业务逻辑部分,在机器内存有限的情况下这样做肯定不好,不过官方貌似也意识到了。 
GreenDao都说好,自己也用了确实不错。但是不得不说确实很复杂,而且在级联这块的配置更复杂一些。之后再次重新考虑数据库框架时写个demo来尝试一下这块。 
LiteOrm虽然名气不大,但是真的很方便,对model类没有限制,级联操作也很方便,效率上和GreenDao差一点也真的可以忽略了。所有目前个人选择使用LiteOrm,也分享给大家。可惜的是LiteOrm没有gradle引入。

本文相关代码在:GitHub LiteOrmLearn 
本文的相关代码在上面,另外官方的samples是eclipse版的,我完全移到as上了。

希望本文能对你有帮助。另外,真的希望Realm能更好,毕竟1.0.0 release已经出来了。

这篇关于Android 数据库框架 LiteOrm使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/679682

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]