GreenDao系列之(2)设计及机制介绍

总体设计类图

以下会分拆成两个部分进行说明:
1、总体机制部分
2、Sql操作细节部分

总体机制

可以看到,有几个重要的类:

  1. AbstractDaoMaster : 总入口类,每个db有相应的AbstractDaoMaster去管理,一般情况下用于创建AbstractDaoSession,并且创建xxxDao的DaoConfig,然后交给AbstractSession进行xxxDao的实例创建。
  2. Database :db抽象接口,有标准的sql实例及sqlcipher加密后的两者实例
  3. AbstractSession :db会话,一个AbstractDaoMaster可以创建多个会话,每个会话拥有该该db下的所有AbstractDao实例,并且决定AbstractDao实例是否使用缓存机制。很难想象多个会话是用在什么场景,一般情况下只会有一个会话。
  4. AbstractDao :数据库table的实体类,用于访问该table的所有操作。AbstractDao有两个泛型,第一个是主键类型,第二个是Entity的类型。AbstractDao提供了增删改查的所有操作,由于对象是Entity,因此修改的value全部以Entity给予的值为准,也就是说每次进行修改的时候,对应的行数据都会以Entity的值进行覆盖。
  5. DaoConfig :数据库table的配置定义,是greenDao的一个重要类。DaoConfig会在AbstractDaoMaster中通过registerDaoClass进行注册。在创建DaoConfig时候,通过反射机制读取xxxDAO的属性,从而生成xxxDao的配置(如column、主键、表名、增删改的语句等信息),用于数据库的增删改查曾操作。
  6. Property :数据库的column定义
  7. IdentityScope :很多人看到这个比较难于理解,按官方的解释:Identity scopes let greenDAO re-use Java objects. 说白了,就是一个缓存类。有两个缓存的类型:
  • IdentityScopeLong
  • IdentityScopeObject
    主要是根据AbstractDao的主键类型选择的,如果主键是Integer、Long,可以IdentityScopeLong,其他使用IdentityScopeObject。可以IdentityScopeLong内部使用自己编写的经过优化过的LongHashMap作为存储对象,效率会更高。

操作细节设计

前面提到DaoConfig是table的配置,其中的配置包括增删改语句的生成。AbstractDao作为table的入口,增删改的操作全部依赖于DaoConfig里的TableStatements。TableStatements包含了几条语句模板:

  1. insertStatement
  2. insertOrReplaceStatement
  3. updateStatement
  4. deleteStatement
  5. countStatement
    用于语句的快速获取。每条语句都是已经生成好的一条sql语句模板,AbstractDao使用时,只需要拿到该模板,然后进行数据的绑定就可以生成最终的sql语句。例子如下:
public DatabaseStatement getInsertOrReplaceStatement() {
    if (insertOrReplaceStatement == null) {
        String sql = SqlUtils.createSqlInsert("INSERT OR REPLACE INTO ", tablename, allColumns);
        DatabaseStatement newInsertOrReplaceStatement = db.compileStatement(sql);
        synchronized (this) {
            if (insertOrReplaceStatement == null) {
                insertOrReplaceStatement = newInsertOrReplaceStatement;
            }
        }
        if (insertOrReplaceStatement != newInsertOrReplaceStatement) {
            newInsertOrReplaceStatement.close();
        }
    }
    return insertOrReplaceStatement;
}

因此,可以看到,插入、更新的时候,虽然可以获取模板生成语句,但也比较笨拙,不支持灵活的根据属性进行更新的操作:假设我们想只更新AbstractDao的某个property,那就只能老老实实的写sql语句的,这点实在是坑!

而最最复杂的查询语句,则是通过QueryBuilder强大的功能进行查询。greenDao查询、更新的操作都是必须每次针对所有column进行操作,不支持部分column的查询和更新。从查询上确实应该如此,因此,在查询的时候,只需要提供灵活的where条件及order等条件供用户输入即可。

QueryBuilder主要包括两部分:

  1. 语句参数
  2. 生成语句并进行查询

语句参数

语句参数包含如下部分

private final WhereCollector<T> whereCollector; //where语句

private StringBuilder orderBuilder; //order标识

private final List<Object> values; //具体where值
private final List<Join<T, ?>> joins; //join值
private final AbstractDao<T, ?> dao;
private final String tablePrefix;

private Integer limit; //limit
private Integer offset; //offert
private boolean distinct;

其中WhereCollector是一个WhereCondition集合,WhereCondition包含两个接口:appendTo及appendValuesTo,用于生成最终的where语句。举个例子,And ProprotyCondition是这样生成的:


@Override
public void appendTo(StringBuilder builder, String tableAlias) {
    SqlUtils.appendProperty(builder, tableAlias, property).append(op);
}

public static StringBuilder appendProperty(StringBuilder builder, String tablePrefix, Property property) {
    if (tablePrefix != null) {
        builder.append(tablePrefix).append('.');
    }
    builder.append('"').append(property.columnName).append('"');
    return builder;
}

QueryBuilder会根据查询的类型生成不同的AbstractQuery,通过AbstractQuery的查询,最终得到查询结果。这里有个很重要的一个类AbstractQueryData。很容易造成误解成AbstractQuery查询得到的数据,其实不是,AbstractQueryData是AbstractQuery的多线程缓存,用于缓存不同的线程下的查询语句。用于查询语句的复用,这也是greenDao高效的原因。

总结

总的来说,

  1. greenDao相比其他ORMLite高效,比原生sql效率低,基于2个原因:
  • 初始化时采用一次反射,一次性构建好DaoConfig,最小化反射带来的负面效果。而其他ORM有些则生成sql语句时每次都使用反射,效率低也是难免的。
  • 缓存使用: Entity缓存、语句缓存复用
  1. greenDao的查询能够比较强大,但反之Update的操作则比较粗糙,有点不友好。
  2. 数据库的创建和更新也未涉及,既然用到了对象,那么就可以根据对象的属性进行数据库的创建及更新。(该点会在以后介绍我的方案)
时间: 2024-11-05 13:04:32

GreenDao系列之(2)设计及机制介绍的相关文章

验证码对抗之路及现有验证机制介绍

验证码对抗之路及现有验证机制介绍 目明@阿里聚安全 yahoo邮箱在九几年的时候,业务深受各种邮箱机器人的困扰,存在着大量的垃圾邮件,于是他们找到了当时仍在读大学的路易斯·冯·安(Luis von Ahn),并设计了经典的图形验证码,即通过简单的扭曲图形文字进行机器的识别. 通过这个简单的图形,他们很快的控制住了垃圾邮件的数量,并将大量的机器人据之门外. 但是即使验证码解决了垃圾邮件的问题,我们仍要提出一个问句: 验证码是必要的吗? 阿里有句简单的话:不忘初心,方得始终. 验证码不是一个功能性的

dubbo源码分析系列(1)扩展机制的实现

1 系列目录 dubbo源码分析系列(1)扩展机制的实现 dubbo源码分析系列(2)服务的发布 dubbo源码分析系列(3)服务的引用 dubbo源码分析系列(4)dubbo通信设计 2 SPI扩展机制 站在一个框架作者的角度来说,定义一个接口,自己默认给出几个接口的实现类,同时允许框架的使用者也能够自定义接口的实现.现在一个简单的问题就是:如何优雅的根据一个接口来获取该接口的所有实现类呢? 这就需要引出java的SPI机制了 2.1 SPI介绍与demo 这些内容就不再多说了,网上搜一下,一

HBase BlockCache系列 - 探求BlockCache实现机制

HBase BlockCache系列第一篇文章<走进BlockCache>从全局视角对HBase中缓存.Memstore等作了简要概述,并重点介绍了几种BlockCache方案及其演进过程,对此还不了解的可以点这里.本文在上文的基础上深入BlockCache内部,对各种BlockCache方案具体工作原理进行详细分析.Note:因为SlabCache方案在0.98版本已经不被建议使用,因此本文不针对该方案进行讲解:至于LRU方案和Bucket方案,因为后者更加复杂,本文也会花更多篇幅详细介绍该

.“.NET研究”Net Discovery系列之-深入理解平台机制与性能影响 (中)

上一篇文章中Aicken为大家介绍了.Net平台的垃圾回收机制与其对性能的影响,这一篇中将继续为大家介绍.Net平台的另一批黑马-JIT.有关JIT的机制分析 ● 机制分析以C#为例,在C#代码运行前,一般会经过两次编译,第一阶段是C#代码向MSIL的编译,第二阶段是IL向本地代码的编译.第一阶段的编译成果是生成托管模块,第二阶段的编译成果是生成本地代码以供运行,从这里各位同学可以看出,第一阶段生成的MSIL是不能直接运行的.必须指出的是JIT在第一次编译IL后,会修改对应方法相应的内存地址入口

一种新的移动APP保持登陆的实现机制介绍

移动APP的特点 移动APP和网页登陆不同的一点就是,App不需要用户每次使用都登陆,增加了易用性, 本文介绍一下App保持登陆的是实现机制 目前常见的机制: 一 使用传统的会话机制session 把网页的机制照搬过来,利用传统网页的记住登陆机制. 用户输入正确的用户名和密码后,创建登陆会话,同时生成一个记住登陆token保持在服务器端,同时发个客户端. 客户端每次启动时,通过记录登陆token新建会话,后续使用便采取session机制. 服务器端的可用Memcache 或 Redis 存储会话

ASP.NET MVC+EF框架+EasyUI实现权限管理系列(13)-权限设计

原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(13)-权限设计 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    (2):数据库访问层的设计Demo    (3):面向接口编程   (4 ):业务逻辑层的封装    (5):前台Jquery easyUI实现    (6):EF上下文实例管理    (7):DBSession的封装   (8):DBSession线程内唯一     (9):TT摸版的学习    (10):V

《游戏机制——高级游戏设计技术》一第 1 章 设计游戏机制

第 1 章 设计游戏机制 游戏机制--高级游戏设计技术游戏机制是游戏核心部分的规则.流程以及数据.它们定义了玩游戏的活动如何进行.何时发生什么事.获胜和失败的条件是什么.本章将介绍五种游戏机制,并说明它们是如何在一些常见的电子游戏类别中得到体现的.本章还会告诉你应该在游戏设计的哪一阶段中设计和构建机制原型,并详细阐述三种原型构建方法,分析各自的优点和缺点.读完本章后,你应该能清晰地理解游戏机制的作用和设计思路了.

.Net Discovery系列之-深入理解平台机制与性“.NET技术”能影响(下)

三.关于异常捕获机制 虽然我们已经很辛苦了,但是仍然有很多原因使代码运行失败,如引用null引用.索引越界.内存溢出.类型转换失败等等.这就需要我们的代码有足够的容错能力,在代码运行失败时,及时.主动的处理这些异常. ● 机制分析 .Net 中基本的异常捕获与处理机制是由try-catch-finally块来完成的,它们分别完成了异常的监测.捕获与处理工作.一个try块可以对应零个或多个catch块,可以对应零个或一个finally块.不过没有catch的try似乎没有什么意义,如果try对应了

.Net Discovery系列之-深入理解平台机制与性能影“.NET研究”响(下)

三.关于异常捕获机制 虽然我们已经很辛苦了,但是仍然有很多原因使代码运行失败,如引用null引用.索引越界.内存溢出.类型转换失败等等.这就需要我们的代码有足够的容错能力,在代码运行失败时,及时.主动的处理这些异常. ● 机制分析 .Net 中基本的异常捕获与处理机制是由try-catch-finally块来完成的,它们分别完成了异常的监测.捕获与处理工作.一个try块可以对应零个或多个catch块,可以对应零个或一个finally块.不过没有catch的try似乎没有什么意义,如果try对应了