首页 > 代码库 > 标识映射(Identify Map)

标识映射(Identify Map)

通过在Map中保存每个已加载过的对象,确保每个对象只加载一次.

  • 当要访问对象时,首先检查标识映射,看需要的对象是否已经存在其中.
  • 使用Identify来确保不重复加载相同的数据,不仅有助于保证正确性(不会将同一数据加载到两个不同的对象上),还能提升性能.
  • 运行机制
    • 基本思想:使用一系列映射.这些映射包含了从DB读出的对象.
    • 键选择
      • 当DB的键只有一列,且不可改变时,最自然的就是DB的主键.
      • 通常,一个以简单数据类型的代理主键,可以作为映射的键.
    • 显示还是通用.
      • 显式的.为每一种需要的对象提供不同的方法.findPerson(1).
        • 推荐.
        • 强类型有利于编译时检查.
        • 显示的接口.
        • 但是每增加一个映射就要加入一个方法.
      • 通用的.为所有的对象提供统一的方法.find("person",1).
        • 易于构造可重复使用的注册表.
        • 新增映射时不需要修改它.
      • 键的类型也会影响它.如果对象的键类型相同,那么通用型很合适.
    • 数量
      • 范围:从一个类对应一个映射,到整个会话对应一个映射.
      • 对于多映射,一般是每个类或者每个表对应一个映射.
        • 当DB方案和对象模型同构时,没有问题.
        • 当不同时,基于对象比较容易.因为对象不知道映射的复杂关系.
      • 对于继承.多个映射分离使得引入多态变得困难.最好一个继承树一个映射.
        • 但是必须保证键在继承树中的唯一性.
      • 单映射的优点是新增DB表时,不必增加新的映射.
    • 放在那里
      • 要确保每个会话都有自己的实例,并独立于其他会话的实例.
      • 当正在使用工作单元时,最好放在工作单元上.
      • 如果没有,捆绑到会话的注册表中.
    • 事务相关
      • 通常一个会话子还有一个单一标识映射.否则,就要为映射提供事务保护.
      • 两个例外
        • 用对象数据库作为事务高速缓存.
        • 在所有条件下都是只读的对象.不必担心这些对象在会话期间的共享问题.
          • 把只读标识映射放在进程上下文中,把可更新的标识映射放在会话上下文中.
  • 使用时机
    • 用一个标识映射来管理所有修改了的数据库读出对象.
      • 主要是不希望出现两个内存对象对应同一条数据库记录的情形.
    • 可作为数据库读取操作的高速缓存.
      • 不需要每次访问某数据都去访问DB.
    • 由于不必担心对不变对象的修改异常,所以其用不着标识映射.
    • 标识印刷有助于避免同一会话中的更新冲突.但它对超出会话的冲突根本无用.