# 金蝶云星空旗舰版 Java 代码模式

## 数据访问模式

### 模式一：BusinessDataServiceHelper 查询

**适用场景：** 按主键或条件查询单个/多个实体

```java
// 按主键查询
DynamicObject entity = BusinessDataServiceHelper.loadSingle(
    ctx, 
    primaryKey, 
    "PUR_POOrder"
);

// 按条件查询
QFilter filter = new QFilter("billno", "=", "PO-001");
DynamicObject[] entities = BusinessDataServiceHelper.load(
    ctx, 
    "PUR_POOrder", 
    new QFilter[]{filter}
);

// 查询指定字段
String[] selectFields = new String[]{"id", "billno", "date", "amount"};
DynamicObject[] entities = BusinessDataServiceHelper.load(
    ctx, 
    "PUR_POOrder", 
    selectFields, 
    new QFilter[]{filter}
);
```

### 模式二：DBRoute SQL 查询

**适用场景：** 复杂查询、报表查询、跨表查询

```java
// 简单查询
String sql = "SELECT FBILLNO, FDATE, FAMOUNT FROM T_PUR_POORDER WHERE FDOCUMENTSTATUS = 'C'";
DataSet ds = DBRoute.queryDataSet("default", sql);

// 带参数查询
String sql = "SELECT * FROM T_PUR_POORDER WHERE FDATE >= ? AND FDATE <= ?";
DataSet ds = DBRoute.queryDataSet("default", sql, new Object[]{startDate, endDate});

// 聚合查询
String sql = "SELECT FSUPPLIERID, SUM(FAMOUNT) AS TOTAL FROM T_PUR_POORDER GROUP BY FSUPPLIERID";
DataSet ds = DBRoute.queryDataSet("default", sql);
```

### 模式三：ORM 查询

**适用场景：** 需要类型安全的查询

```java
// 使用 DataAccess
DataAccess da = new DataAccess(ctx);
DataSet ds = da.executeDataSet("SELECT * FROM T_PUR_POORDER WHERE FID = ?", new Object[]{id});
```

---

## 事务处理模式

### 事务内操作

```java
// 开始事务
DBRoute.beginTransaction();
try {
    // 业务操作
    DBRoute.execute("default", sql1);
    DBRoute.execute("default", sql2);
    
    // 提交事务
    DBRoute.commitTransaction();
} catch (Exception e) {
    // 回滚事务
    DBRoute.rollbackTransaction();
    throw e;
}
```

### 使用 try-with-resources

```java
try (TransactionScope scope = new TransactionScope()) {
    // 业务操作
    DBRoute.execute("default", sql1);
    DBRoute.execute("default", sql2);
    
    scope.complete();
}
```

---

## 异常处理模式

### 业务异常处理

```java
public void processOrder(DynamicObject order) {
    try {
        // 业务逻辑
        validateOrder(order);
        saveOrder(order);
    } catch (KDException e) {
        // 业务异常，记录日志并抛出
        logger.error("处理订单失败: " + e.getMessage(), e);
        throw e;
    } catch (Exception e) {
        // 其他异常，包装为业务异常
        logger.error("系统异常: " + e.getMessage(), e);
        throw new KDException("SYS001", "系统异常，请联系管理员", e);
    }
}
```

### 校验异常处理

```java
public void validateOrder(DynamicObject order) {
    List<String> errors = new ArrayList<>();
    
    // 校验必填字段
    if (StringUtils.isEmpty(order.getString("billno"))) {
        errors.add("单据编号不能为空");
    }
    
    // 校验业务规则
    BigDecimal amount = order.getBigDecimal("amount");
    if (amount.compareTo(BigDecimal.ZERO) <= 0) {
        errors.add("金额必须大于零");
    }
    
    // 抛出校验异常
    if (!errors.isEmpty()) {
        throw new KDException("VALIDATE001", String.join("; ", errors));
    }
}
```

---

## 日志记录模式

### 使用 Logger

```java
private static final Logger logger = Logger.getLogger(OrderPlugin.class);

// 记录信息
logger.info("开始处理订单: " + billNo);

// 记录警告
logger.warn("订单金额较大: " + amount);

// 记录错误
logger.error("处理订单失败", exception);

// 调试日志
if (logger.isDebugEnabled()) {
    logger.debug("订单详情: " + order.toString());
}
```

---

## 批量处理模式

### 批量查询

```java
// 分批查询大量数据
int batchSize = 1000;
int offset = 0;
List<DynamicObject> allResults = new ArrayList<>();

while (true) {
    String sql = String.format(
        "SELECT * FROM T_PUR_POORDER ORDER BY FID OFFSET %d ROWS FETCH NEXT %d ROWS ONLY",
        offset, batchSize
    );
    DataSet ds = DBRoute.queryDataSet("default", sql);
    
    if (ds.getRowCount() == 0) break;
    
    while (ds.next()) {
        // 处理每行数据
        allResults.add(convertToEntity(ds));
    }
    
    offset += batchSize;
}
```

### 批量更新

```java
// 使用事务批量更新
DBRoute.beginTransaction();
try {
    for (DynamicObject entity : entities) {
        String sql = "UPDATE T_PUR_POORDER SET FSTATUS = ? WHERE FID = ?";
        DBRoute.execute("default", sql, new Object[]{"C", entity.getLong("id")});
    }
    DBRoute.commitTransaction();
} catch (Exception e) {
    DBRoute.rollbackTransaction();
    throw e;
}
```

---

## 缓存使用模式

### 基础资料缓存

```java
// 使用缓存加载基础资料
DynamicObject supplier = BusinessDataServiceHelper.loadSingle(
    ctx, 
    supplierId, 
    "BD_Supplier"
);

// 缓存会自动管理，无需手动清理
```

### 自定义缓存

```java
// 使用 CacheManager
CacheManager cacheManager = CacheManager.getInstance();
String cacheKey = "supplier_" + supplierId;

DynamicObject supplier = (DynamicObject) cacheManager.get(cacheKey);
if (supplier == null) {
    supplier = BusinessDataServiceHelper.loadSingle(ctx, supplierId, "BD_Supplier");
    cacheManager.put(cacheKey, supplier, 300); // 缓存5分钟
}
```
