第十一天-《企业应用架构模式》-对象-关系行为模式
1. 工作单元
用于维护受业务事务影响的对象列表,并协调变化的写入和并发问题的解决。如下:
1)运行机制:
关键:
是提交时,决定要做什么。它打开一个事务,做所有的并发检查(使用悲观离线锁或乐观离线锁)并向数据库写入所做的修改。(开发人员根本不用显示调用数据库更新方法)
记录对象更新的方法:
调用者注册方式:用户如果改变了某个对象就必须将他注册到工作单元,任何没有注册的对象提交时都不会写入数据库。
对象注册方式:注册方法置于对象中,从数据库加载对象会将加载的对象注册为“干净”的,setting方法将要设置的对象注册为“脏”的。
工作单元控制器:工作单元控制所有数据库的读操作,一旦对象被读取,将将它注册为“干净”的对象。工作单元在读操作时将产生一个拷贝,在提交时比较当前对象和拷贝对象(这种的办法是指发生改变的对象),看对象是否发生了改变。
用途:数据库(使用引用完整性时保证更新顺序、批量更新)、事务资源(调整消息队列、事务监控)
.Net环境工作单元实现:使用无连接的数据集,每一行都有版本(当前版本、原始版本、建议版本)、状态(不变、增加、删除、修改)概念
2)使用时机:
基本目的:记录操作过的各种对象,以便知道为了使内存中数据与数据库同步需要考虑哪些对象。
2. 标识映射
通过在映射中保存每个已经加载的对象,确保每个对象只加载一次。当要访问对象时,通过映射来查找它们。
1)运行机制:
键选择:
数据表主键(或其他简单的数据类型)
显示的还是通用的(如findPerson(1),还是find("Person", 1)?):当所有对象键类型相同时使用通用的,其他情况下使用显示的
数量(单映射、多映射):(没看明白)
标识映射存放位置:有工作单元时,放在工作单元;没有工作单元时,捆绑到会话的注册表
2)使用时机:
一般来说,用一个标识映射来管理所有修改了的数据库读出数据;
作为数据库读取操作的告诉缓存。
3. 延迟加载
一个对象,它虽然不包含所需要的所有数据,但是知道怎么获取这些数据
1)运行机制:
4种实现方法:
延迟初始化:
实现思想:每次访问属性域都要先检查该域是否为空。如果为空,在返回域值之前计算出这个域的值(注意这个域需要自封装,即便是类的内部也只能通过它来访问)
优缺点:简单,但往往会在对象和数据库间强加依赖关系
适用场景:活动记录、表数据库入口、行数据入口
虚代理:
定义:虚代理是这样一个对象,它看起来应该是域中的一个对象,但实际上它并不包含任何东西。只有当他的一个方法被调用时,它才从数据库加载适当的对象
优缺点:看上去完全就是需要的对象,但并不真的是那个对象,容易陷入标识问题;同一个实对象,可能有多个不同对象特征的虚代理(需要覆盖Equals方法,而不用标识方法)
适用场景:数据映射器
值保持器:
实现思想:要想获取某对象,可以访问值保持器得到它的值,但只有第一次访问值保持器时它才真正从数据库读取数据
优缺点:可避免标识问题;类需要知道值保持器的存在,丧失强数据类型显式性;
重影:
实现思想:当从数据库加载对象时,它只包含其ID。当每次要访问某个域时,它就会加载其完全状态(可以把域数据分为不同组,按需加载)
延迟加载的问题:
继承(虚代理、重影,需要知道要创建什么类型的重影或虚对象);
波动加载(产生超出需要的数据库访问),影响应用程序性能(解决办法:不适用延迟加载集合中的项,但集合整体可以延迟加载)
适用场景:面向方面的程序(将延迟加载置于一个单独的方面,能独立改变延迟加载策略)
2)使用时机:
最佳时机:需要额外的调用,并且当使用主对象时所调用的数据没有到的时候(取决于加载一个对象时需要从数据库读取多少数据和数据库调用的次数)