# 04 · 推理引擎集成实现

> 目标：用 Apache Jena 加载 OWL 本体，实现推理（等价识别、维度层级展开、指标推导）。

## 1. Maven 依赖

```xml
<dependency>
    <groupId>org.apache.jena</groupId>
    <artifactId>apache-jena-libs</artifactId>
    <version>4.10.0</version>
</dependency>
```

## 2. 加载本体 + 启用推理

```java
import org.apache.jena.ontology.*;
import org.apache.jena.query.*;

// OWL 推理模型（含 RDFS + OWL 规则推理）
OntModel model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM_RULE_INF);
model.read("metric.ttl");   // 加载 Turtle 本体
```

`OWL_MEM_RULE_INF` 支持传递性（TransitiveProperty）、等价类（equivalentClass）等推理规则，MVP 够用。

## 3. 三个核心推理场景

### 3.1 等价识别（成交额 ≡ GMV）

```java
String sparql = """
    PREFIX : <http://example.org/metric-ontology#>
    PREFIX owl: <http://www.w3.org/2002/07/owl#>
    SELECT ?m WHERE { ?m owl:equivalentClass :GMV }
    """;
try (QueryExecution qe = QueryExecutionFactory.create(sparql, model)) {
    ResultSet rs = qe.execSelect();
    // 结果：成交额、销售额
}
```

### 3.2 维度层级展开（华东区 ⊇ 各省）

```java
String sparql = """
    PREFIX : <http://example.org/metric-ontology#>
    SELECT ?region WHERE { ?region :partOf :华东区 }
    """;
// 结果：上海、江苏、浙江、安徽、福建、江西、山东（partOf 是 TransitiveProperty，自动递归）
```

### 3.3 指标推导（客单价 = GMV ÷ 订单数）

```java
String sparql = """
    PREFIX : <http://example.org/metric-ontology#>
    SELECT ?component WHERE { :客单价 :composedOf ?component }
    """;
// 结果：GMV、订单数
```

## 4. 封装成服务（Spring Bean）

```java
@Service
public class OntologyService {
    private final OntModel model;

    public OntologyService() {
        this.model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM_RULE_INF);
        this.model.read("metric.ttl");   // 路径从配置读
    }

    /** 等价指标识别：传入"成交额"，返回规范指标 GMV */
    public String resolveEquivalentMetric(String rawMetric) {
        // SPARQL 查 owl:equivalentClass，返回等价的本体概念
    }

    /** 维度层级展开：传入"华东区"，返回省份列表 */
    public List<String> expandRegion(String region) {
        // SPARQL 查 :partOf，返回所有子成员
    }

    /** 指标推导：传入"客单价"，返回组成指标列表 */
    public List<String> getComponents(String metric) {
        // SPARQL 查 :composedOf
    }

    /** 查映射：返回指标映射的物理字段 */
    public String getMappedColumn(String metric) {
        // SPARQL 查 :mapsToColumn
    }
}
```

## 5. 关键注意

- **推理模型用 `OWL_MEM_RULE_INF`**（不是普通 Model），否则等价/传递推理不生效
- **本体文件放资源目录**，路径从配置读
- **推理结果可缓存**：本体稳定，推理结果可缓存避免重复推理
- **性能**：本体小时内存推理足够；本体大了再考虑 TDB 持久化 + 增量推理
