对象缓存机制是SunvStation地理编辑系统的核心组件，用于在批量创建和修改地理对象时提供高效的内存管理。该机制通过在内存中暂存对象，避免频繁的数据库I/O操作，显著提升大批量数据处理的性能。缓存机制区分了新建对象和修改对象两种场景，分别采用不同的缓存策略，并通过统一的事务性接口完成数据库持久化。

Sources: [PySSProcess.py](PySSProcess.py#L26-L46)

## 缓存架构概述

对象缓存机制采用多层次的缓存架构，通过SSProcessManager类的成员变量管理不同类型的缓存。缓存系统分为三大类别：新建对象缓存、修改对象缓存和删除对象缓存，每种类别又进一步区分为地物对象和注记对象。

```mermaid
classDiagram
    class SSProcessManager {
        +GeoBaseList bufferObjList
        +GeoBaseList bufferNoteList
        +list newBufferObjList
        +list newBufferNoteList
        +tuple curNewObj
        +GeoBaseList delBufferGeoList
        +createNewObjByCode(code)
        +setNewObjValue(field, value)
        +addNewObjPoint(x, y, z, type, name)
        +addNewObjToSaveObjList()
        +saveBufferObjToDatabase()
    }
    
    class GeoEditMixin {
        <<Mixin>>
        +transMemoDataToExtendAttr(geoList)
        +persistTempGeoList(geoVec)
        +persistTempNoteList(noteVec)
    }
    
    class GeoBaseList {
        +append(geo)
        +empty()
        +clear()
    }
    
    class GeoBase {
        +getObjectType()
        +getCode()
        +setMemoData(fields, values)
        +getDatasetName()
    }
    
    SSProcessManager *-- GeoBaseList : 管理缓存列表
    SSProcessManager *-- GeoBase : 封装几何对象
    SSProcessManager --> GeoEditMixin : 继承缓存操作
    GeoBaseList o-- GeoBase : 包含对象
```

该架构体现了**关注点分离**的设计原则：SSProcessManager负责缓存容器管理，GeoEditMixin提供缓存操作的具体实现，GeoBase和GeoBaseList作为数据载体。缓存对象以pair形式存储，其中第一个元素是GeoObject实例（包含数据集引用和唯一ID），第二个元素是具体的几何对象（PointObject、LineObject、AreaObject或MarkNote）。

Sources: [ssprocess_mixins/geo_edit_mixin.py](ssprocess_mixins/geo_edit_mixin.py#L28-L54)

## 缓存类型与分类

缓存机制根据对象状态和类型进行明确分类，这种设计使得系统能够对不同场景采用优化的处理策略。

### 按操作状态分类

| 缓存类型 | 存储容器 | 对象来源 | 持久化方式 | 典型应用场景 |
|---------|---------|---------|-----------|------------|
| 新建对象缓存 | `newBufferObjList` / `newBufferNoteList` | 脚本创建的新对象 | `addGeoObject()` 添加到地图 | 批量导入数据、程序化生成地物 |
| 修改对象缓存 | `bufferObjList` / `bufferNoteList` | 从地图加载并修改的对象 | `saveDatabase()` 更新数据库 | 属性批量更新、几何形状编辑 |
| 删除对象缓存 | `delBufferGeoList` | 标记为删除的对象 | `delGeoBaseComponent()` 执行删除 | 清理过期数据、对象合并操作 |
| 当前新建对象 | `curNewObj` | 正在创建过程中的临时对象 | 转移至其他缓存或丢弃 | 交互式创建、参数化建模 |

### 按对象类型分类

地物对象和注记对象的物理存储位置不同，系统通过`getObjectType()`方法进行类型识别（e_Point_Obj=0、e_Line_Obj=1、e_Area_Obj=2、e_Note_Obj=3），并自动路由到相应的缓存容器中。

Sources: [PySSProcess.py](PySSProcess.py#L32-L40)

## 缓存生命周期管理

对象的生命周期在缓存系统中遵循明确的阶段划分，从对象创建开始，经过属性设置和几何编辑，最终通过事务性接口持久化到数据库。

```mermaid
flowchart LR
    A[开始创建对象] --> B{创建方式}
    B -->|通过编码创建| C[createNewObjByCode]
    B -->|通过注记类创建| D[createNewObjByClass]
    B -->|默认类型创建| E[createDefaultGeoBase]
    
    C --> F[curNewObj 临时缓存]
    D --> F
    E --> F
    
    F --> G[setNewObjValue 设置属性]
    G --> H[addNewObjPoint 添加坐标点]
    H --> I{下一步操作}
    
    I -->|加入选择集| J[addNewObjToSelObjList]
    I -->|加入保存列表| K[addNewObjToSaveObjList]
    I -->|放弃创建| L[deleteNewObj]
    
    K --> M[newBufferObjList/newBufferNoteList]
    J --> N[selGeoList/selNoteList]
    
    M --> O[saveBufferObjToDatabase 批量保存]
    N --> O
    
    O --> P[transMemoDataToExtendAttr 属性转换]
    P --> Q[map.addGeoObject 添加到地图]
    Q --> R[map.saveDatabase 写入数据库]
    R --> S[清除缓存列表]
```

该生命周期体现了**延迟加载**和**批量处理**的优化策略：对象在内存中完成所有编辑操作，仅在最后阶段才与数据库交互，显著减少了网络往返和数据锁争用。

Sources: [ssprocess_mixins/geo_edit_mixin.py](ssprocess_mixins/geo_edit_mixin.py#L120-L210)

## 核心API详解

### 对象创建API

`createNewObjByCode()` 是新建对象的主要入口，通过编码获取地物定义并创建相应类型的几何对象。该方法会自动从当前数据源获取特征定义，包括对象类型、颜色、线型、线宽等属性，并应用到新创建的对象上。

```python
# 通过编码创建新地物对象
obj, geo = SSProcess.createNewObjByCode(3103013)
if obj is not None:
    # 设置对象属性
    SSProcess.setNewObjValue("SSObj_Name", "新建道路")
    SSProcess.setNewObjValue("[宽度]", "15.5")
    
    # 添加坐标点（线对象）
    SSProcess.addNewObjPoint(100.0, 200.0, 0.0, 0, "")
    SSProcess.addNewObjPoint(150.0, 250.0, 0.0, 0, "")
    
    # 将对象加入保存列表
    SSProcess.addNewObjToSaveObjList()
```

Sources: [ssprocess_mixins/geo_edit_mixin.py](ssprocess_mixins/geo_edit_mixin.py#L133-L163)

### 属性设置API

`setNewObjValue()` 方法支持基本属性和扩展属性的统一设置。基本属性以`SSObj_`前缀标识，扩展属性使用方括号`[]`包裹。该方法还支持批量设置多个扩展属性，通过逗号分隔属性名和值。

**属性设置对比表：**

| 属性类型 | 语法格式 | 存储位置 | 转换逻辑 |
|---------|---------|---------|---------|
| 基本属性 | `SSObj_Name` | 对象内置字段 | 直接映射到GeoBase的getter/setter |
| 单个扩展属性 | `[自定义字段名]` | MemoData字段 | 通过StringArray键值对存储 |
| 批量扩展属性 | `[字段1],[字段2]` | MemoData字段 | 解析后分别设置键值对 |

Sources: [ssprocess_mixins/geo_edit_mixin.py](ssprocess_mixins/geo_edit_mixin.py#L193-L260)

### 批量持久化API

`saveBufferObjToDatabase()` 是缓存机制的核心事务接口，负责将所有缓存中的对象持久化到数据库。该方法按数据集分组处理对象，先调用`addGeoObject()`添加新对象，再通过`transMemoDataToExtendAttr()`将MemoData转换为扩展属性，最后调用`saveDatabase()`提交修改。

```mermaid
sequenceDiagram
    participant API as saveBufferObjToDatabase()
    participant Cache as 缓存列表
    participant Map as ScaleMap
    participant DB as 数据库
    
    API->>Cache: 读取newBufferObjList/newBufferNoteList
    API->>API: 按数据集分组
    loop 每个数据集分组
        API->>Map: addGeoObject(geoList)
        API->>Map: setExtentAttr(geo, fields, values)
    end
    API->>Cache: 清空newBufferObjList/newBufferNoteList
    
    API->>Cache: 读取bufferObjList/bufferNoteList
    API->>Map: setExtentAttr(geo, fields, values)
    API->>Map: saveDatabase(geoList)
    API->>Cache: 清空bufferObjList/bufferNoteList
    
    API->>Map: delGeoBaseComponent(delBufferGeoList)
    API->>Cache: 清空delBufferGeoList
```

该方法实现了**原子性**的事务特性：所有缓存对象的保存操作作为一个整体提交，成功则全部生效，失败则回滚至保存前状态。同时，通过数据集分组优化了数据库锁粒度，提高了并发性能。

Sources: [ssprocess_mixins/geo_edit_mixin.py](ssprocess_mixins/geo_edit_mixin.py#L475-L508)

### 备忘数据转换API

`transMemoDataToExtendAttr()` 方法负责将对象的备忘数据（MemoData）转换为扩展属性。这是必要的中间步骤，因为MemoData是Python层面的临时存储格式，而扩展属性是数据库层面的持久化格式。

转换过程在事务边界内进行（`beginSetExtentAttr()` / `endSetExtentAttr()`），确保扩展属性设置的原子性。对于具有大量扩展属性的对象，该操作可能产生显著的性能开销，建议批量处理时控制对象数量。

Sources: [ssprocess_mixins/geo_edit_mixin.py](ssprocess_mixins/geo_edit_mixin.py#L464-L473)

## 缓存与选择集的关系

缓存列表与选择集是两个独立但相关的容器系统。选择集（`selGeoList`、`selNoteList`）用于对象的逻辑分组和查询，而缓存列表（`bufferObjList`、`newBufferObjList`等）用于对象的事务性持久化。

**关系对比表：**

| 容器类型 | 主要用途 | 数据来源 | 是否持久化 | 清除时机 |
|---------|---------|---------|-----------|---------|
| 选择集 | 逻辑分组、批量查询 | 从地图加载或新建对象添加 | 否 | clearSelection()手动清除 |
| 新建对象缓存 | 事务性保存新对象 | 通过createNewObjByCode创建 | 是 | saveBufferObjToDatabase()自动清除 |
| 修改对象缓存 | 事务性更新现有对象 | 从选择集加载并修改 | 是 | saveBufferObjToDatabase()自动清除 |
| 删除对象缓存 | 事务性删除对象 | 标记为删除的对象 | 是 | saveBufferObjToDatabase()自动清除 |

`addNewObjToSelObjList()` 和 `addNewObjToSaveObjList()` 方法体现了这种分离设计：前者将对象加入选择集进行后续查询或操作，后者将对象加入缓存列表准备持久化。一个对象可以同时存在于两个容器中，也可以仅存在于其中一个。

Sources: [ssprocess_mixins/geo_edit_mixin.py](ssprocess_mixins/geo_edit_mixin.py#L415-L430)

## 最佳实践与注意事项

### 批量操作的性能优化

对于大量对象的批量操作，建议遵循以下最佳实践：

1. **避免频繁调用saveBufferObjToDatabase()**：该方法会触发数据库事务，每次调用都有固定开销。应累积足够多的对象后再批量保存，建议每1000-5000个对象保存一次。

2. **合理使用数据集分组**：虽然`saveBufferObjToDatabase()`内部已实现数据集分组，但在创建对象时尽量按数据集顺序添加对象，可以减少分组操作的复杂度。

3. **控制扩展属性数量**：每个对象的扩展属性存储在MemoData中，过多扩展属性会增加内存占用和序列化开销。建议将高频查询的属性映射为基本属性，低频属性作为扩展属性。

### 内存管理注意事项

缓存对象在Python层面持有C++对象的引用，可能导致内存泄漏。以下场景需要特别关注：

- **对象创建后未加入保存列表**：如果调用了`createNewObjByCode()`但未调用`addNewObjToSaveObjList()`或`addNewObjToSelObjList()`，对象会一直保留在`curNewObj`中，占用内存直到下一次创建操作覆盖。

- **事务中断后的缓存清理**：如果在调用`saveBufferObjToDatabase()`之前发生异常，缓存列表中的对象不会被自动清理。建议在异常处理中手动调用缓存清除操作或重新创建SSProcess实例。

### 并发安全注意事项

缓存机制不是线程安全的。如果在多线程环境下使用，需要通过外部同步机制（如线程锁）确保对SSProcess实例的访问序列化。系统设计的典型使用场景是单线程的脚本执行环境。

### 与撤销系统的集成

缓存机制与[撤销标记管理](25-che-xiao-biao-ji-guan-li)功能存在交互。如果需要在保存到数据库前支持撤销操作，应将对象同时添加到选择集和保存列表中，这样可以在不触发数据库提交的情况下回滚修改。

## 相关主题

对象缓存机制是地理编辑功能链中的关键环节。掌握缓存机制后，建议继续学习以下相关主题：

- **[批量保存到数据库](24-pi-liang-bao-cun-dao-shu-ju-ku)**：深入了解`saveBufferObjToDatabase()`方法的实现细节和性能调优策略
- **[创建默认地物对象](19-chuang-jian-mo-ren-di-wu-dui-xiang)**：学习通过不同方式创建地物对象的方法和编码映射关系
- **[地物基本属性详解](17-di-wu-ji-ben-shu-xing-xiang-jie)**：了解基本属性的完整列表和语义说明
- **[扩展属性与自定义属性](18-kuo-zhan-shu-xing-yu-zi-ding-yi-shu-xing)**：掌握扩展属性的存储机制和访问方法
- **[对象删除操作](22-shan-chu-dui-xiang-cao-zuo)**：理解删除缓存的工作原理和事务性保证