Selaa lähdekoodia

neo4j数据源切换到postgresql数据源

yuchengwei 2 kuukautta sitten
vanhempi
commit
e664a1e11c

+ 4 - 3
src/main/java/com/qizhen/healsphere/facade/KgFacade.java

@@ -6,8 +6,9 @@ import cn.hutool.json.JSONUtil;
 import com.qizhen.healsphere.common.exception.CommonErrorCode;
 import com.qizhen.healsphere.common.exception.CommonException;
 import com.qizhen.healsphere.repository.mapper.entity.PresetInfo;
-import com.qizhen.healsphere.repository.neo4j.BaseNodeRepository;
+import com.qizhen.healsphere.repository.postgresql.NodeRepository;
 import com.qizhen.healsphere.service.impl.KgServiceImpl;
+import com.qizhen.healsphere.service.impl.KgServicePostgresImpl;
 import com.qizhen.healsphere.web.dto.*;
 import com.qizhen.healsphere.web.param.KgQuery;
 import com.qizhen.healsphere.web.param.KgTree;
@@ -26,11 +27,11 @@ import java.util.concurrent.atomic.AtomicLong;
  * @time: 2018/8/6 9:11
  */
 @Component
-public class KgFacade extends KgServiceImpl {
+public class KgFacade extends KgServicePostgresImpl {
     @Autowired
     private PresetInfoFacade presetInfoFacade;
     @Autowired
-    private BaseNodeRepository baseNodeRepository;
+    private NodeRepository baseNodeRepository;
 
 
     public List<NodeDTO> getNode(KgQuery kgQuery){

+ 139 - 0
src/main/java/com/qizhen/healsphere/repository/postgresql/EdgeRepository.java

@@ -0,0 +1,139 @@
+package com.qizhen.healsphere.repository.postgresql;
+
+import com.qizhen.healsphere.repository.neo4j.BaseNodeRepository;
+import com.qizhen.healsphere.repository.neo4j.entity.BaseEntity;
+import com.qizhen.healsphere.repository.neo4j.entity.BaseRelationship;
+import com.qizhen.healsphere.repository.neo4j.entity.Edge;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Repository;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Repository
+public class EdgeRepository {
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @Autowired
+    private NodeRepository nodeRepository;
+
+    private final RowMapper<Map<String, Object>> edgeMapper = (rs, rowNum) -> {
+        Map<String, Object> map = new HashMap<>();
+        map.put("id", rs.getLong("id"));
+        map.put("category", rs.getString("category"));
+        map.put("src_id", rs.getLong("src_id"));
+        map.put("dest_id", rs.getLong("dest_id"));
+        map.put("name", rs.getString("name"));
+        map.put("version", rs.getString("version"));
+        map.put("status", rs.getInt("status"));
+        return map;
+    };
+
+    /**
+     * 检查关系是否存在
+     */
+    public Boolean isExistRelationship(String startLabel, Long startId, String endLabel, Long endId, String relationshipType) {
+        String sql = "SELECT COUNT(*) FROM kg_edges WHERE src_id = ? AND dest_id = ? AND category = ? AND status != -1";
+        int count = jdbcTemplate.queryForObject(sql, Integer.class, startId, endId, relationshipType);
+        return count > 0;
+    }
+
+    /**
+     * 创建关系
+     */
+    public void createRelationship(String startLabel, Long startId, String endLabel, Long endId, String relationshipType, Map<String, Object> properties) {
+        String sql = "INSERT INTO kg_edges (category, src_id, dest_id, name, status) VALUES (?, ?, ?, ?, 0)";
+        jdbcTemplate.update(
+            sql,
+            relationshipType,
+            startId,
+            endId,
+            relationshipType
+        );
+    }
+
+    /**
+     * 更新关系
+     */
+    public void updateRelationship(String oldRelationshipType, String newRelationshipType) {
+        String sql = "UPDATE kg_edges SET category = ?,name = ? WHERE category = ? AND status != -1";
+        jdbcTemplate.update(sql, newRelationshipType, newRelationshipType, oldRelationshipType);
+    }
+
+    /**
+     * 根据关系名字模糊查询关系类型
+     */
+    public List<String> findRelationshipNames(String name) {
+        String sql = "SELECT DISTINCT category FROM kg_edges WHERE category LIKE ? AND status != -1";
+        return jdbcTemplate.queryForList(sql, String.class, "%" + name + "%");
+    }
+
+    /**
+     * 删除关系
+     */
+    public void deleteRelationship(String startLabel, Long startId, String endLabel, Long endId, String relationshipType) {
+        String sql = "UPDATE kg_edges SET status = -1 WHERE src_id = ? AND dest_id = ? AND category = ?";
+        jdbcTemplate.update(sql, startId, endId, relationshipType);
+    }
+
+    /**
+     * 获取三元组关系
+     */
+    public List<Edge> triples(String startLabel, String relationship, String endLabel) {
+        String sql = "SELECT e.*, n1.category as start_category, n2.category as end_category " +
+                    "FROM kg_edges e " +
+                    "JOIN kg_nodes n1 ON e.src_id = n1.id " +
+                    "JOIN kg_nodes n2 ON e.dest_id = n2.id " +
+                    "WHERE n1.category = ? AND n2.category = ? AND e.category = ? " +
+                    "AND e.status != -1 AND n1.status != -1 AND n2.status != -1";
+
+        return jdbcTemplate.query(sql, (rs, rowNum) -> {
+            Edge edge = new Edge();
+            
+            // 设置起始节点
+            Map<String, Object> startNode = nodeRepository.findNodeById(rs.getLong("src_id"));
+            edge.setStartNode(buildBaseEntity(startNode));
+            
+            // 设置结束节点
+            Map<String, Object> endNode = nodeRepository.findNodeById(rs.getLong("dest_id"));
+            edge.setEndNode(buildBaseEntity(endNode));
+            
+            // 设置关系
+            BaseRelationship baseRelationship = new BaseRelationship();
+            baseRelationship.setId(rs.getLong("id"));
+            baseRelationship.setType(rs.getString("category"));
+            
+            Map<String, Object> properties = new HashMap<>();
+            properties.put("name", rs.getString("name"));
+            properties.put("version", rs.getString("version"));
+            properties.put("status", rs.getInt("status"));
+            baseRelationship.setProperties(properties);
+            
+            edge.setRelationship(baseRelationship);
+            
+            return edge;
+        }, startLabel, endLabel, relationship);
+    }
+
+    private BaseEntity buildBaseEntity(Map<String, Object> nodeMap) {
+        BaseEntity entity = new BaseEntity();
+        entity.setId((Long) nodeMap.get("id"));
+        entity.setName((String) nodeMap.get("name"));
+        
+        ArrayList<String> labels = new ArrayList<>();
+        labels.add((String) nodeMap.get("category"));
+        entity.setLabel(labels);
+        
+        Map<String, Object> properties = new HashMap<>((Map<String, Object>) nodeMap.get("properties"));
+        properties.remove("name");
+        entity.setProperties(properties);
+        
+        return entity;
+    }
+}

+ 289 - 0
src/main/java/com/qizhen/healsphere/repository/postgresql/NodeRepository.java

@@ -0,0 +1,289 @@
+package com.qizhen.healsphere.repository.postgresql;
+
+import cn.hutool.core.map.MapUtil;
+import com.qizhen.healsphere.repository.neo4j.entity.BaseEntity;
+import com.qizhen.healsphere.repository.neo4j.param.MergeNodeParam;
+import com.qizhen.healsphere.web.dto.NodeDTO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Repository;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Repository
+public class NodeRepository {
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    private final RowMapper<Map<String, Object>> nodeMapper = (rs, rowNum) -> {
+        Map<String, Object> map = new HashMap<>();
+        map.put("id", rs.getLong("id"));
+        map.put("name", rs.getString("name"));
+        map.put("category", rs.getString("category"));
+        map.put("layout", rs.getString("layout"));
+        map.put("version", rs.getString("version"));
+        map.put("status", rs.getInt("status"));
+        return map;
+    };
+
+    /**
+     * 根据名字和标签查询实体属性
+     * @param category
+     * @param name
+     * @return 实体map
+     */
+    public Map<String, Object> findNodeByName(String category, String name) {
+        String sql = "SELECT * FROM kg_nodes WHERE category = ? AND name = ? AND status != -1";
+        List<Map<String, Object>> results = jdbcTemplate.query(sql, nodeMapper, category, name);
+        return results.isEmpty() ? new HashMap<>() : results.get(0);
+    }
+
+    public List<NodeDTO> findNodeByNameLike(String category, String name) {
+        String sql = "SELECT id, name, category FROM kg_nodes WHERE category = ? AND name LIKE ? AND status != -1 LIMIT 20";
+        return jdbcTemplate.query(sql, (rs, rowNum) -> {
+            NodeDTO nodeDTO = new NodeDTO();
+            nodeDTO.setNodeId(rs.getLong("id"));
+            nodeDTO.setName(rs.getString("name"));
+            nodeDTO.setLabel(rs.getString("category"));
+            return nodeDTO;
+        }, category, "%" + name + "%");
+    }
+
+    /**
+     * 根据id查询实体属性
+     * @param id
+     * @return 实体map
+     */
+    public Map<String, Object> findNodeById(Long id) {
+        String sql = "SELECT * FROM kg_nodes WHERE id = ? AND status != -1";
+        List<Map<String, Object>> results = jdbcTemplate.query(sql, nodeMapper, id);
+        return results.isEmpty() ? new HashMap<>() : results.get(0);
+    }
+
+    /**
+     * 根据名字模糊查询实体
+     * @param category
+     * @param name
+     * @return 实体map列表
+     */
+    public List<Map<String, Object>> findNodeListByName(String category, String name) {
+        String sql = "SELECT * FROM kg_nodes WHERE category = ? AND name LIKE ? AND status != -1";
+        List<Map<String, Object>> mapList = jdbcTemplate.query(sql, nodeMapper, category, "%" + name + "%");
+        if (!mapList.isEmpty()) {
+            mapList.forEach(map -> {
+                HashMap<Object, Object> hashMap = MapUtil.newHashMap();
+                hashMap.put("name", map.get("name"));
+                map.put("properties", hashMap);
+                List<String> list = new ArrayList<>();
+                list.add(map.get("category").toString());
+                map.put("labels",list);
+            });
+        }
+        return mapList;
+    }
+
+    /**
+     * 新增实体
+     * @param category
+     * @param properties
+     * @return 实体map
+     */
+    public Map<String, Object> createNode(String category, Map<String, Object> properties) {
+        String sql = "INSERT INTO kg_nodes (name, category, status) VALUES (?, ?, 0) RETURNING *";
+        List<Map<String, Object>> results = jdbcTemplate.query(
+            sql,
+            nodeMapper,
+            properties.get("name"),
+            category
+        );
+        return results.isEmpty() ? new HashMap<>() : results.get(0);
+    }
+
+    /**
+     * 更新实体名称
+     * @param nodeId
+     * @param name
+     * @return 实体map
+     */
+    public Map<String, Object> updateNode(Long nodeId, String name) {
+        String sql = "UPDATE kg_nodes SET name = ? WHERE id = ? AND status != -1 RETURNING *";
+        List<Map<String, Object>> results = jdbcTemplate.query(sql, nodeMapper, name, nodeId);
+        return results.isEmpty() ? new HashMap<>() : results.get(0);
+    }
+
+    /**
+     * 删除实体
+     * @param nodeId
+     */
+    public void deleteNode(Long nodeId) {
+        String sql = "UPDATE kg_nodes SET status = -1 WHERE id = ?";
+        jdbcTemplate.update(sql, nodeId);
+    }
+
+    /**
+     * 获取所有实体
+     * @param category
+     * @return 实体列表
+     */
+    public List<BaseEntity> getAll(String category) {
+        String sql = "SELECT * FROM kg_nodes WHERE category = ? AND status != -1";
+        return jdbcTemplate.query(sql, (rs, rowNum) -> {
+            BaseEntity entity = new BaseEntity();
+            entity.setId(rs.getLong("id"));
+            entity.setName(rs.getString("name"));
+            ArrayList<String> labels = new ArrayList<>();
+            labels.add(rs.getString("category"));
+            entity.setLabel(labels);
+            
+            Map<String, Object> properties = new HashMap<>();
+            properties.put("layout", rs.getString("layout"));
+            properties.put("version", rs.getString("version"));
+            properties.put("status", rs.getInt("status"));
+            entity.setProperties(properties);
+            
+            return entity;
+        }, category);
+    }
+
+    /**
+     * 根据名字和标签查询实体
+     * @param label 标签
+     * @param name 名称
+     * @return 实体
+     */
+    public BaseEntity byName(String label, String name) {
+        String sql = "SELECT * FROM kg_nodes WHERE category = ? AND name = ? AND status != -1";
+        List<BaseEntity> results = jdbcTemplate.query(sql, (rs, rowNum) -> {
+            BaseEntity entity = new BaseEntity();
+            entity.setId(rs.getLong("id"));
+            entity.setName(rs.getString("name"));
+            ArrayList<String> labels = new ArrayList<>();
+            labels.add(rs.getString("category"));
+            entity.setLabel(labels);
+            
+            Map<String, Object> properties = new HashMap<>();
+            properties.put("layout", rs.getString("layout"));
+            properties.put("version", rs.getString("version"));
+            properties.put("status", rs.getInt("status"));
+            entity.setProperties(properties);
+            
+            return entity;
+        }, label, name);
+        return results.isEmpty() ? null : results.get(0);
+    }
+
+    /**
+     * 创建新实体
+     * @param label 标签
+     * @param properties 属性
+     * @return 实体
+     */
+    public BaseEntity create(String label, Map<String, Object> properties) {
+        if (properties == null) {
+            properties = new HashMap<>();
+        }
+        properties.put("is_deleted", "N");
+        
+        String sql = "INSERT INTO kg_nodes (name, category, layout, version, status) VALUES (?, ?, ?, ?, 0) RETURNING *";
+        List<BaseEntity> results = jdbcTemplate.query(
+            sql,
+            (rs, rowNum) -> {
+                BaseEntity entity = new BaseEntity();
+                entity.setId(rs.getLong("id"));
+                entity.setName(rs.getString("name"));
+                ArrayList<String> labels = new ArrayList<>();
+                labels.add(rs.getString("category"));
+                entity.setLabel(labels);
+                
+                Map<String, Object> props = new HashMap<>();
+                props.put("layout", rs.getString("layout"));
+                props.put("version", rs.getString("version"));
+                props.put("status", rs.getInt("status"));
+                entity.setProperties(props);
+                
+                return entity;
+            },
+            properties.get("name"),
+            label,
+            properties.get("layout"),
+            properties.get("version")
+        );
+        return results.isEmpty() ? null : results.get(0);
+    }
+
+    /**
+     * 合并两个实体
+     * @param mergeNodeParam 合并参数
+     * @return 合并后的实体
+     */
+    public Map<String, Object> mergeNode(MergeNodeParam mergeNodeParam) {
+        // 1. 获取原始节点的属性
+        Map<String, Object> firstNode = findNodeById(mergeNodeParam.getFirstId());
+        Map<String, Object> secondNode = findNodeById(mergeNodeParam.getSecondId());
+        
+        if (firstNode.isEmpty() || secondNode.isEmpty()) {
+            throw new RuntimeException("One or both nodes not found");
+        }
+
+        // 2. 创建新节点,合并属性
+        Map<String, Object> newNodeProps = new HashMap<>();
+        newNodeProps.put("name", mergeNodeParam.getNewName());
+        newNodeProps.put("category", mergeNodeParam.getNewLabel());
+        newNodeProps.put("status", 0);
+        newNodeProps.put("layout", firstNode.get("layout"));
+        newNodeProps.put("version", firstNode.get("version"));
+
+        String insertSql = "INSERT INTO kg_nodes (name, category, layout, version, status) VALUES (?, ?, ?, ?, ?) RETURNING *";
+        List<Map<String, Object>> newNodeResults = jdbcTemplate.query(
+            insertSql,
+            nodeMapper,
+            newNodeProps.get("name"),
+            newNodeProps.get("category"),
+            newNodeProps.get("layout"),
+            newNodeProps.get("version"),
+            newNodeProps.get("status")
+        );
+
+        if (newNodeResults.isEmpty()) {
+            throw new RuntimeException("Failed to create new node");
+        }
+
+        Map<String, Object> newNode = newNodeResults.get(0);
+        Long newNodeId = (Long) newNode.get("id");
+
+        // 3. 在事务中迁移关系并删除原节点
+        org.springframework.transaction.support.TransactionTemplate transactionTemplate = 
+            new org.springframework.transaction.support.TransactionTemplate(
+                new org.springframework.jdbc.datasource.DataSourceTransactionManager(jdbcTemplate.getDataSource()));
+
+        transactionTemplate.execute(status -> {
+            try {
+                // 处理出向关系
+                String updateOutgoingEdgesSql = "UPDATE kg_edges SET src_id = ? WHERE src_id = ? AND status != -1";
+                jdbcTemplate.update(updateOutgoingEdgesSql, newNodeId, mergeNodeParam.getFirstId());
+                jdbcTemplate.update(updateOutgoingEdgesSql, newNodeId, mergeNodeParam.getSecondId());
+
+                // 处理入向关系
+                String updateIncomingEdgesSql = "UPDATE kg_edges SET dest_id = ? WHERE dest_id = ? AND status != -1";
+                jdbcTemplate.update(updateIncomingEdgesSql, newNodeId, mergeNodeParam.getFirstId());
+                jdbcTemplate.update(updateIncomingEdgesSql, newNodeId, mergeNodeParam.getSecondId());
+
+                // 将原节点标记为删除
+                String updateSql = "UPDATE kg_nodes SET status = -1 WHERE id IN (?, ?)";
+                jdbcTemplate.update(updateSql, mergeNodeParam.getFirstId(), mergeNodeParam.getSecondId());
+
+                return null;
+            } catch (Exception e) {
+                status.setRollbackOnly();
+                throw new RuntimeException("Failed to merge nodes: " + e.getMessage(), e);
+            }
+        });
+
+        return newNode;
+    }
+}

+ 87 - 0
src/main/java/com/qizhen/healsphere/repository/postgresql/PropertyRepository.java

@@ -0,0 +1,87 @@
+package com.qizhen.healsphere.repository.postgresql;
+
+import com.qizhen.healsphere.repository.neo4j.param.UpdatePropertyParam;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Repository;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Repository
+public class PropertyRepository {
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    private final RowMapper<Map<String, Object>> propertyMapper = (rs, rowNum) -> {
+        Map<String, Object> map = new HashMap<>();
+        map.put("id", rs.getLong("id"));
+        map.put("category", rs.getInt("category"));
+        map.put("ref_id", rs.getLong("ref_id"));
+        map.put("prop_name", rs.getString("prop_name"));
+        map.put("prop_value", rs.getString("prop_value"));
+        map.put("prop_title", rs.getString("prop_title"));
+        map.put("type", rs.getShort("type"));
+        return map;
+    };
+
+    /**
+     * 新增实体属性
+     * @param category
+     * @param nodeId
+     * @param properties
+     * @return 属性map
+     */
+    public Map<String, Object> createProperty(String category, Long nodeId, Map<String, Object> properties) {
+        String sql = "INSERT INTO kg_props (category, ref_id, prop_name, prop_value, prop_title, type) VALUES (?, ?, ?, ?, ?, ?) RETURNING *";
+        List<Map<String, Object>> results = jdbcTemplate.query(
+            sql,
+            propertyMapper,
+            0, // category默认为0
+            nodeId,
+            properties.keySet().stream().findFirst().get(),
+            properties.values().stream().findFirst().get(),
+            properties.keySet().stream().findFirst().get(),
+            1
+        );
+        return results.isEmpty() ? new HashMap<>() : results.get(0);
+    }
+
+    /**
+     * 删除实体属性
+     * @param category
+     * @param nodeId
+     * @param propertyName
+     * @return 删除的属性map
+     */
+    public Map<String, Object> deleteProperty(String category, Long nodeId, String propertyName) {
+        String deleteSql = "DELETE FROM kg_props WHERE ref_id = ? AND prop_name = ?";
+        jdbcTemplate.update(deleteSql, nodeId, propertyName);
+
+        String selectSql = "SELECT * FROM kg_props WHERE ref_id = ? AND prop_name = ?";
+        List<Map<String, Object>> properties = jdbcTemplate.query(selectSql, propertyMapper, nodeId, propertyName);
+        
+        return properties.isEmpty() ? new HashMap<>() : properties.get(0);
+    }
+
+    /**
+     * 更新实体属性
+     * @param updatePropertyParam
+     * @return 更新后的属性map
+     */
+    public Map<String, Object> updateProperty(UpdatePropertyParam updatePropertyParam) {
+        String sql = "UPDATE kg_props SET prop_name = ?, prop_value = ? WHERE ref_id = ? AND prop_name = ? RETURNING *";
+        List<Map<String, Object>> results = jdbcTemplate.query(
+            sql,
+            propertyMapper,
+            updatePropertyParam.getNewPropertyName(),
+            updatePropertyParam.getNewPropertyValue(),
+            updatePropertyParam.getNodeId(),
+            updatePropertyParam.getOldPropertyName()
+        );
+        return results.isEmpty() ? new HashMap<>() : results.get(0);
+    }
+}

+ 9 - 5
src/main/java/com/qizhen/healsphere/service/impl/EntityServiceImpl.java

@@ -1,23 +1,27 @@
 package com.qizhen.healsphere.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
-import com.qizhen.healsphere.repository.neo4j.BaseNodeRepository;
-import com.qizhen.healsphere.repository.neo4j.param.MergeNodeParam;
 import com.qizhen.healsphere.repository.neo4j.entity.BaseEntity;
+import com.qizhen.healsphere.repository.neo4j.param.MergeNodeParam;
+import com.qizhen.healsphere.repository.postgresql.NodeRepository;
 import com.qizhen.healsphere.service.EntityService;
-import com.qizhen.healsphere.web.EntityController;
 import com.qizhen.healsphere.web.vo.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 @Service
 public class EntityServiceImpl implements EntityService {
 
+//    @Autowired
+//    BaseNodeRepository nodeRepository;
     @Autowired
-    BaseNodeRepository nodeRepository;
+    NodeRepository nodeRepository;
 
 
     @Override

+ 165 - 0
src/main/java/com/qizhen/healsphere/service/impl/KgServicePostgresImpl.java

@@ -0,0 +1,165 @@
+package com.qizhen.healsphere.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import com.qizhen.healsphere.service.KgService;
+import com.qizhen.healsphere.web.dto.BaseNodeRSDTO;
+import com.qizhen.healsphere.web.dto.GraphDTO;
+import com.qizhen.healsphere.web.dto.NextNodeDTO;
+import com.qizhen.healsphere.web.param.KgQuery;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * PostgreSQL实现版本的知识图谱服务
+ *
+ * @author trae
+ */
+@Service("kgServicePostgres")
+public class KgServicePostgresImpl implements KgService {
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    private Map<String, Object> getNodeProperties(Long nodeId) {
+        String propSql = "SELECT prop_title, prop_value FROM kg_props WHERE ref_id = ?";
+        List<Map<String, Object>> propResults = jdbcTemplate.query(
+            propSql,
+            (rs, rowNum) -> {
+                Map<String, Object> prop = new HashMap<>();
+                prop.put(rs.getString("prop_title"), rs.getString("prop_value"));
+                return prop;
+            },
+            nodeId
+        );
+        
+        Map<String, Object> properties = new HashMap<>();
+        propResults.forEach(prop -> properties.putAll(prop));
+        return properties;
+    }
+
+    @Override
+    public List<GraphDTO> getGraph(KgQuery kgQuery) {
+        List<GraphDTO> graphDTOList = new ArrayList<>();
+        Map<String, GraphDTO> graphMap = new HashMap<>();
+        Map<String, List<NextNodeDTO>> rtypeMap = new HashMap<>();
+
+        // 1. 查询中心节点
+        String nodeSql = "SELECT n.id, n.name, n.category " +
+                "FROM kg_nodes n " +
+                "WHERE n.category = ? AND n.name = ? " +
+                "AND n.status = '0' ";
+
+        jdbcTemplate.query(nodeSql, new Object[]{kgQuery.getLabelName(), kgQuery.getInputStr()},
+                (rs, rowNum) -> {
+                    String sName = rs.getString("name");
+                    String sLabel = rs.getString("category");
+                    long sId = rs.getLong("id");
+                    Map<String, Object> sProp = getNodeProperties(sId);
+                    sProp.put("name", sName);
+
+                    GraphDTO graphDTO = new GraphDTO();
+                    graphDTO.setName(sName);
+                    graphDTO.setLabel(sLabel);
+                    graphDTO.setId(sId);
+                    graphDTO.setProperties(sProp);
+                    graphMap.put(sName + "_" + sLabel, graphDTO);
+                    return null;
+                });
+
+        // 2. 查询关联的边和目标节点
+        String relationSql = "SELECT e.name as rType, m.id as target_id, m.name as target_name, " +
+                "m.category as target_label, " +
+                "(SELECT COUNT(*) FROM kg_edges WHERE src_id = m.id) as pCount " +
+                "FROM kg_nodes n " +
+                "JOIN kg_edges e ON n.id = e.src_id " +
+                "JOIN kg_nodes m ON e.dest_id = m.id " +
+                "WHERE n.category = ? AND n.name = ? " +
+                "AND n.status = '0' " +
+                "ORDER BY e.name";
+
+        jdbcTemplate.query(relationSql, new Object[]{kgQuery.getLabelName(), kgQuery.getInputStr()},
+                (rs, rowNum) -> {
+                    String rType = rs.getString("rType");
+                    String eName = rs.getString("target_name");
+                    String eLabel = rs.getString("target_label");
+                    long eId = rs.getLong("target_id");
+                    Map<String, Object> eProp = getNodeProperties(eId);
+                    eProp.put("name", eName);
+                    int pCount = rs.getInt("pCount");
+
+                    NextNodeDTO nextNodeDTO = new NextNodeDTO();
+                    nextNodeDTO.setName(eName);
+                    nextNodeDTO.setLabel(eLabel);
+                    nextNodeDTO.setPCount(pCount);
+                    nextNodeDTO.setId(eId);
+                    nextNodeDTO.setProperties(eProp);
+
+                    List<NextNodeDTO> nextNodeDTOS = rtypeMap.computeIfAbsent(rType, k -> new ArrayList<>());
+                    nextNodeDTOS.add(nextNodeDTO);
+                    return null;
+                });
+
+        // 3. 组装返回结果
+        if (CollUtil.isNotEmpty(graphMap)) {
+            GraphDTO graphDTO = graphMap.values().iterator().next();
+            List<BaseNodeRSDTO> baseNodeRSDTOS = new ArrayList<>();
+
+            rtypeMap.forEach((key, value) -> {
+                BaseNodeRSDTO nodeRSDTO = new BaseNodeRSDTO();
+                nodeRSDTO.setRType(key);
+                nodeRSDTO.setENodeDTOS(value);
+                baseNodeRSDTOS.add(nodeRSDTO);
+            });
+
+            graphDTO.setENodeRSDTOS(baseNodeRSDTOS);
+            graphDTOList.add(graphDTO);
+        }
+
+        return graphDTOList;
+    }
+
+    @Override
+    public List<Map<String, Object>> getGraphNew(KgQuery kgQuery) {
+        String sql = "SELECT n.id as source_id, n.label as sLabel, n.name as sName, e.type as rType, " +
+                "m.id as target_id, m.label as eLabel, m.name as eName, " +
+                "(SELECT COUNT(*) FROM kg_edges WHERE source_id = m.id) as pCount " +
+                "FROM kg_nodes n " +
+                "JOIN kg_edges e ON n.id = e.source_id " +
+                "JOIN kg_nodes m ON e.target_id = m.id " +
+                "WHERE n.label = ? AND n.name = ? " +
+                "AND (n.is_deleted = 'N' OR n.is_deleted IS NULL) " +
+                "AND m.label IN ('疾病', '症状', '药品通用名', '手术和操作', '实验室检查', '辅助检查') " +
+                "ORDER BY e.type";
+
+        List<Map<String, Object>> results = jdbcTemplate.queryForList(sql, kgQuery.getLabelName(), kgQuery.getInputStr());
+        
+        // 为每个节点添加属性信息
+        for (Map<String, Object> result : results) {
+            Long sourceId = ((Number) result.get("source_id")).longValue();
+            Long targetId = ((Number) result.get("target_id")).longValue();
+            
+            Map<String, Object> sourceProps = getNodeProperties(sourceId);
+            Map<String, Object> targetProps = getNodeProperties(targetId);
+            
+            result.put("sProps", sourceProps);
+            result.put("eProps", targetProps);
+        }
+
+        return results;
+    }
+
+    /**
+     * 解析JSON格式的属性字符串为Map
+     */
+    private Map<String, Object> parseProperties(String propertiesJson) {
+        // 这里需要根据实际存储格式实现属性的解析
+        // 可以使用Jackson或Gson等JSON库进行解析
+        return new HashMap<>(); // 临时返回空Map,需要实现具体的解析逻辑
+    }
+}

+ 4 - 2
src/main/java/com/qizhen/healsphere/service/impl/PropertyServiceImpl.java

@@ -1,8 +1,8 @@
 package com.qizhen.healsphere.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
-import com.qizhen.healsphere.repository.neo4j.BasePropertyRepository;
 import com.qizhen.healsphere.repository.neo4j.param.UpdatePropertyParam;
+import com.qizhen.healsphere.repository.postgresql.PropertyRepository;
 import com.qizhen.healsphere.service.PropertyService;
 import com.qizhen.healsphere.web.vo.DeletePropertyVO;
 import com.qizhen.healsphere.web.vo.EntityVO;
@@ -17,8 +17,10 @@ import java.util.stream.Collectors;
 @Service
 public class PropertyServiceImpl implements PropertyService {
 
+//    @Autowired
+//    BasePropertyRepository propertyRepository;
     @Autowired
-    BasePropertyRepository propertyRepository;
+    PropertyRepository propertyRepository;
 
 
     @Override

+ 5 - 11
src/main/java/com/qizhen/healsphere/service/impl/RelationshipServiceImpl.java

@@ -1,33 +1,27 @@
 package com.qizhen.healsphere.service.impl;
 
-import com.qizhen.healsphere.repository.neo4j.BaseNodeRepository;
-import com.qizhen.healsphere.repository.neo4j.BaseRelationshipRepository;
-import com.qizhen.healsphere.service.EntityService;
+import com.qizhen.healsphere.repository.postgresql.EdgeRepository;
 import com.qizhen.healsphere.service.RelationshipService;
-import com.qizhen.healsphere.web.vo.EntityVO;
 import com.qizhen.healsphere.web.vo.RelationshipNameVO;
 import com.qizhen.healsphere.web.vo.RelationshipVO;
 import com.qizhen.healsphere.web.vo.UpdateRelationTypeVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
 
 @Service
 public class RelationshipServiceImpl implements RelationshipService {
 
+//    @Autowired
+//    BaseRelationshipRepository relationshipRepository;
     @Autowired
-    BaseRelationshipRepository relationshipRepository;
-
+    EdgeRepository relationshipRepository;
 
     @Override
     public Boolean createRelationship(List<RelationshipVO> relationshipList) {
         try {
-            relationshipList.stream().forEach(relationship ->
+            relationshipList.forEach(relationship ->
                     relationshipRepository.createRelationship(
                             relationship.getStartLabel(),
                             relationship.getStartId(),

+ 6 - 1
src/main/resources/application-local.yml

@@ -8,7 +8,12 @@ spring:
       driver-class-name: org.postgresql.Driver
       username: knowledge
       password: qwer1234.
-#      jdbc-url: jdbc:mysql://173.18.12.194:3306/sys-ltkg?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false
+      max-lifetime: 300000  # 5 分钟(单位:毫秒)
+      validation-timeout: 5000  # 5 秒超时
+      connection-test-query: SELECT 1
+      connection-timeout: 30000
+      maximum-pool-size: 10
+  #      jdbc-url: jdbc:mysql://173.18.12.194:3306/sys-ltkg?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false
 #      driver-class-name: com.mysql.cj.jdbc.Driver
 #      username: root
 #      password: dsYun8!@#

+ 5 - 0
src/main/resources/application-test.yml

@@ -5,6 +5,11 @@ spring:
       driver-class-name: org.postgresql.Driver
       username: knowledge
       password: qwer1234.
+      max-lifetime: 300000  # 5 分钟(单位:毫秒)
+      validation-timeout: 5000  # 5 秒超时
+      connection-test-query: SELECT 1
+      connection-timeout: 30000
+      maximum-pool-size: 10
 
   neo4j:
     uri: bolt://173.18.12.206:7687