- 浏览: 117754 次
- 来自: ...
文章分类
最新评论
假设我们必须处理对象的存储, 加载, 和查询. 性能和引用完整性的约束, 给接口的实现带来了以下问题:
-
加载根对象时如何避免加载大半个数据库
-
存储时如何更新整个对象图
-
存储时如何高效的更新整个对象图
-
何时同步对象的内存状态和持久存储状态
-
如何确保在出错时保持对象内存状态和持久存储状态之间的一致性
-
如何保证引用的唯一性以避免可能的更新冲突
对性能的精益求精, 又促使人们解决更多的细节问题:
-
N+1查询问题
-
分离查询模型和存储模型
-
尽量减少查询语句
这些问题的解决方案又会带来新的问题.
1. 加载根对象时如何避免加载大半个数据库
更多的时候这是一个建模问题, 为什么我只需要显示一点信息, 更新一点信息, 却拉家带口把八杆子打不着的亲戚都带上 : 细粒度对象设计, 直接访问需要的信息, 减少所谓根对象的存在
一个workaround是延迟加载, 当你无法修复你错误的建模时, 当真正去访问子对象的时候再发出查询语句去加载. 这个方案会带来如下问题:
-
查询语句较多. 无解, 延迟意味着至少两条SQL语句, 只能尽量减少
-
延迟加载的时机, 是自动透明的延迟加载, 还是用户确定何时加载
Hibernate可通过配置文件指定是否lazy load, 一旦指定, 后面的load就是透明的在访问子对象时发生. 也可在发出每次查询时显式指定
Entity Framework则要求用户在每一次查询时显式指定包含哪个子对象, 对没有指定包含的子对象, 只能在访问前显示使用load(). 理由是决定加载不加载,何时加载都是程序员的责任
-
然而更大的问题是如何管理数据库连接, 要确保延迟加载的时候数据库连接是开着的
可以使用Interceptor等技术维持 Session per request, Open Session in View pattern(处理好异常等, 确保session会关闭).
能在一个 Session 中使用两个事务吗?
是的,这事实上是这种模式(Open Session In View)的一个更好的实现。在一个请求事件中,一个数据库事务用于数据的读写。第二个数据库事务仅用于在渲染视图期间读数据。在这点上没有对对象的修改。因此,数据库锁早在第一个事务时就被释放了,这使得应用有更好的可伸缩性,第二个事务可以被优化。要使用两阶段的事务,你需要比 Servlet Filter 更强大的拦截器 - AOP 是个很好的选择。JBoss Seam 使用了这种模式。
为什么 Hibernate 不在需要时就加载 Object?
每个月很多人都会有这种想法,为什么 Hibernate 不能在有需要的就开启一个新的数据库连接(更有效率的是开启一个 Session),然后加载集合或是初始化代理,而是选择抛出一个 LazyInitializationException。当然,这种想法,第一眼看上去可能是明智之举。但这种做法有很多的缺点,只有当你考虑特别的事务访问时才会发现。
如果 Hibernate 可以进行任意的数据库连接和事务,这种操作是开发人员不可知,并且也是在任何事务边界之外的,那还要事务边界做什么。当 Hibernate 开启了新的数据库连接去加载集合,但同时集合的拥有者却被删除了,这是将会发生什么?(注意,这种情况是不会发生在上面提到的两阶段的事务模式中的 - 单个 Session 可对实体可重复读。)当所有的对象都可以通过关联导航获取时为什么还要有 Service 层?这种方式将消耗多少内存?哪些对象要首先被清除掉?所有这些问题都是无解的,因为 Hibernate 是一个在线的事务处理服务(并包含一些批处理操作),并不是一个“在未定义的工作单元中从数据持久仓库取得对象”的服务。此外,对于 n+1 查询问题,我们是否需要 n+1 的事务和连接的问题?
这个问题的解决方案当然是正确的工作单元划分和设计,支撑其的拦截技术就像这里所展现的一样,并且/或者正确的抓取技术,使得特定工作单元所需的全部信息能够以最小的影响、最好的性能和伸缩性被获得。
2. 存储时如何更新整个对象图
框架支持级联更新. 是否应该级联更新, 哪些操作可以级联, 哪些不可以, 对象之间的哪些类型的关联可以级联, 哪些不可以, 则是程序员的责任
-
通常被聚合的对象, 其生命周期应由父对象负责, 新增/更新/删除都应级联
-
自身有存在意义的实体, 可以级联更新, 但不应删除和新增
3. 存储时如何高效的更新整个对象图
常用工作单元模式, Unit of Work.
4. 何时同步对象的内存状态和持久存储状态
任何改动都立即提交到数据库会带来额外开销. 一个时机是事务提交时.
Hibernate: 每间隔一段时间,Session会执行一些必需的SQL语句来把内存中的对象的状态同步到JDBC连接中。这个过程被称为刷出(flush),默认会在下面的时间点执行:
-
在某些查询执行之前
-
在调用org.hibernate.Transaction.commit()的时候
-
在调用Session.flush()的时候
5. 如何确保在出错时保持对象内存状态和持久存储状态之间的一致性
数据库事务回滚, 清空内存缓存, 重新加载
6. 如何避免或处理可能的更新冲突
保证引用的唯一性: 使用单一的加载入口和缓存, Identity Map .
乐观离线锁会引入更新冲突问题, 一般使用Versioning来解决, 类似版本控制系统的更新问题; 但业务对象很少能自动Merge, Merge的语义也不好定义, 所以一般检测到冲突之后只好重做了, 或者取决于业务逻辑, Last Win也是一种策略.
7. N+1查询问题
-
Eager Load + JOIN
-
截然不同的一种避免N+1次查询的方法是,使用二级缓存。
N + 1 是关联引入的问题, 网上的解释和例子倾向于拿one-2-many说事, 但实际上one-2-one依然面临使用多于一条SQL语句加载的问题
8. 分离查询模型和存储模型
适合业务关系的对象模型未必对查询是高效的. 需要单独针对查询建模, 可以用单独的索引表来实现. 在更新业务对象的存储时同时更新索引表
9. 尽量减少查询语句
比如join over multiple select, 比如批量抓取
10. 值类型
不需要有ID, 通常被聚合. 有对应的Class, 但一般没有对应的Table, 仅是Table中的几个字段
挑战在于将对象语言类型系统(和开发者定义的实体和值类型)映射到 SQL/数据库类型系统。 Hibernate: 提供了连接两个系统之间的桥梁:对于实体类型,我们使用class, subclass 等等。对于值类型,我们使用 property, component 及其他,通常跟随着type属性。这个属性的值是Hibernate 的映射类型的名字
发表评论
-
Architecture is layered
2004-12-11 11:57 374那天被问道软件架构师需要了解编程语言的细节吗? 呵呵,架构是 ... -
Thinking Everyday
2004-12-11 12:01 4351,编程语言的发展趋势 ... -
糟糕命名集锦
2004-12-11 16:50 5661,公交支线,如375和375 ... -
古代的软件开发 (一)
2005-02-19 16:45 6721,额外的中间层鞋子:人类发明鞋子的意义无论如何评价都不过分, ... -
访问控制 : 语言和平台
2005-03-15 19:27 608程序逻辑上的组织方式(如名称空间,包等)可以和部署时的分发 ... -
Thinking Everyday II
2005-03-17 15:11 6151, 是业务,不是技术,傻瓜 是集成,不是编程 是使用,不 ... -
内容与标准为王:下一代互联网与下一代搜索
2005-07-25 14:53 697第一代互联网混淆了真正的数据和它的表现形式,第一代搜索无法 ... -
个性与定制为王:下一代互联网和下一代门户
2005-07-28 11:28 593看一下现在我与互联网有关的生活:我有两三个常用的Web邮箱 ... -
泛型编程 vs. 面向对象
2005-08-10 14:30 804面向对象:封装(数据抽象)是基础,继承是手段,多态是目的 ... -
函数式编程 vs. 对象式编程
2005-08-10 14:44 646<<我爱我家>>有一集和平摔成了脑 ... -
用手机从ATM取钱
2005-11-21 22:49 690手机的以下两个特性,使它潜在的可能成为统一的支付和信用平 ... -
Web 3.0 : Unified Human-like Interaction
2006-01-14 16:31 696你还在到搜索引擎的主页上去搜索吗?你还登录新闻网站查询最新比赛 ... -
软件生物学
2006-01-14 16:59 644长久以来,软件的建筑学隐喻已经深入人心,可始终无法达到建筑 ... -
广义对象论
2006-01-25 15:31 681前几天本想接着以前的思维中对“3.2 Programming ... -
Thinking Everyday III
2006-03-26 14:17 7821, RAII让我告别了delete,IoC让我告别了ne ... -
简单至及的AOP和IOC
2006-03-26 14:21 654I. AOP的例子 1, Google To ... -
TDD: Tricky Driven Development
2007-05-10 07:07 587命名 测试用例的名字应该描述需求, 不要描述实现. ... -
Thinking Everyday IV
2007-05-15 04:36 5131, 实际上 C# 2.0 已经部 ... -
迭代本质论
2008-02-14 13:58 624新年伊始, 可能你又要制定一些计划了, 实际上, 你的生活在开 ... -
建筑的永恒之道
2004-08-10 18:31 6442,质 这种特质是任 ...
相关推荐
当与JsonStore.Sql扩展包一起使用时,它也可以作为微型Orm。 入门 添加NuGet参考 PM > Install-Package JsonStore.Sql 给定以下要存储的类 public class Foo { public string Id { get ; set ; } public string ...
这需要 通过设计完成,因为让DTO回写到,比方说:域模型或其他东西,就会更改它的持久性,同时人们也认为它是反模式的。在这种解决方案中,命令消息在双向映射 中往往是更好的选择。然而,在某些特定环境中,有人...
WhereIN(字段字符串,作用域[] interface {}) WhereNotIn(字段字符串,范围[] interface {}) WhereBetween(字段字符串,左字符串,右字符串) WhereNull(fields ... string):选择为空细分
创建您自己的易于理解或与您的问题域相匹配的内容。 或者只是去掉那些令人讨厌的下划线... 。 使更新和创建新对象变得容易快捷 可选的字段验证和默认值 仲裁者没有给您的东西: 一种修改Salesforce对象和模式的...
基于 Spring 的多域、多模块示例 Web 项目这是一个使用Springframework的多模块项目,在域处理方式中使用ORM和Mybatis创建业务逻辑后,配置项目示例,使得Web区可以根据需要使用Orm或Mybatis域。项目结构 multi-...
原则ORM + ODM快速入门介绍我们将为HelloFresh域的非常简化的版本编写一个小型应用程序。 在编写此应用程序时,我们将看到Data Mapper和Repository模式如何实现域和基础结构之间的清晰隔离。 我们将使用MySQL存储...
(该项目正在寻找新的维护者)模拟ORM Analogue是适用于PHP的灵活,易于使用的ORM 。 这是附带Laravel框架采用数据映射模式,而不是原来的Active ... 使用这个简单的域模型: use Analogue \ ORM \ Entity ;use Ill
YB.ORM是用于C ++的对象关系映射(ORM)的工具。 受到Hibernate或SQLAlchemy之类的启发。 应该与数据库无关。 包括用于域对象代码生成的工具。 表的元数据描述是一个XML文件。
JFinal 是基于 Java 语言的极速 WEB ORM 框架,其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展、Restful。在拥有Java语言所有优势的同时再拥有ruby、python等动态语言的开发效率!为您...
Couchbase Lite ORM仅将文档转换为您的域对象,反之亦然。 您不需要扩展任何类。 您只需要注释您的班级。 该库将不使用反射。 反思是太慢了。下载Gradle: compile ' ...
由于他们将SQL隐藏在泄漏抽象之后执行,因此,对问题进行诊断和故障排除需要对ORM的内部运作有深入的了解。 光子查询只是普通SQL,因此您始终确切知道ORM正在运行的查询。 Photon是唯一支持流畅API的Java ORM之一。...
Gallus - 可以的小 ORM。 Gallus 是一个受启发的微 ORM,它遵循与 Dapper 相同的精神,但它... 作为开发人员,我们希望编写代码并专注于问题域,而编写 SQL 被视为不必要的分心,这是 ORM 寻求解决的困难。 我认为这是
在使用Laravel的Eloquent ORM时,我们常常需要处理模型之间的关联关系,这时,with方法和whereHas方法是两个经常被用到的查询作用域(query scope),它们分别用于预加载关联数据和筛选特定条件的关联数据。...
- 域对象的保存和检索 - 数据库表和列名更改的处理 - 预保存和后检索逻辑的集中 - 复杂连接以获取相关项目 - 从对象模型创建数据库模式 7. 为何需要Hibernate XML映射文件? Hibernate的XML映射文件告诉Hibernate...
概念模型描述问题域的实体和关系,关系数据模型基于此建立数据库的静态结构,而域模型是面向对象的设计模型,包含实体域对象、过程域对象和事件域对象。域对象间的关联、依赖、聚集和一般化构成了对象间复杂的关系...
支持的一流ORM是 支持的一流消息总线是 基于消息 每个域层都提供了一组使用它的消息。 通常,消息被分类为命令消息,事件消息和查询消息。 主要优点是我们可以直观地创建独立的业务逻辑流。 它通过在Web和CLI中...
作用域通常用于Eloquent ORM,是处理复杂查询时的一个强大工具。本文将深入探讨Laravel中的作用域应用程序绑定及其在实际开发中的应用。 一、Eloquent ORM与作用域 Eloquent是Laravel提供的一个强大的ORM(对象...
- **概念模型**:用于描述问题域中的实体及其关系,不涉及具体实现细节。 - **关系数据模型**:定义数据库结构,包括表、索引、视图等。 - **域模型**:在软件设计阶段创建,包括实体、过程、事件等类型的域对象。 ...
xUtils3简介 xUtils包含了orm,http,图像,视图注解,但依然很轻量级(251K),并且...支持cookie(实现域,路径,有效期等特性) 支持缓存(实现了Cache-Control,Last-Modified,ETag等特性,缓存内容过多时使用过期