فهرست منبع

postgresql数据库相关接口修改

yuchengwei 5 ماه پیش
والد
کامیت
e524ebcc21

+ 5 - 25
pom.xml

@@ -53,43 +53,23 @@
             <artifactId>junit</artifactId>
             <scope>test</scope>
         </dependency>
-
-
-
-<!--        <dependency>-->
-<!--            <groupId>com.baomidou</groupId>-->
-<!--            <artifactId>mybatis-plus-boot-starter</artifactId>-->
-<!--            <version>3.1.2</version>-->
-<!--            <exclusions>-->
-<!--                <exclusion>-->
-<!--                    <artifactId>mybatis-spring</artifactId>-->
-<!--                    <groupId>org.mybatis</groupId>-->
-<!--                </exclusion>-->
-<!--                <exclusion>-->
-<!--                    <artifactId>mybatis</artifactId>-->
-<!--                    <groupId>org.mybatis</groupId>-->
-<!--                </exclusion>-->
-<!--            </exclusions>-->
-<!--        </dependency>-->
-
         <dependency>
             <groupId>org.mybatis.spring.boot</groupId>
             <artifactId>mybatis-spring-boot-starter</artifactId>
             <version>2.1.1</version>
         </dependency>
 
-<!--        <dependency>-->
-<!--            <groupId>com.baomidou</groupId>-->
-<!--            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>-->
-<!--            <version>3.0.0</version>-->
-<!--        </dependency>-->
-
         <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
             <scope>runtime</scope>
         </dependency>
 
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-data-neo4j</artifactId>

+ 25 - 0
src/main/java/com/qizhen/healsphere/repository/mapper/KgCountInfoMapper.java

@@ -0,0 +1,25 @@
+package com.qizhen.healsphere.repository.mapper;
+
+import com.qizhen.healsphere.repository.mapper.entity.KgCountInfo;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 知识统计信息信息 Mapper 接口
+ * </p>
+ */
+@Mapper
+public interface KgCountInfoMapper {
+    List<KgCountInfo> getCountList(@Param("pageSize") Integer pageSize,@Param("offset") Integer offset);
+
+    Integer count();
+
+    List<KgCountInfo> calculateDetailInfo();
+
+    void clearTable();
+
+    void batchInsert(List<KgCountInfo> list);
+}

+ 20 - 0
src/main/java/com/qizhen/healsphere/repository/mapper/KgCountTotalInfoMapper.java

@@ -0,0 +1,20 @@
+package com.qizhen.healsphere.repository.mapper;
+
+import com.qizhen.healsphere.repository.mapper.entity.KgCountTotalInfo;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 知识统计信息信息 Mapper 接口
+ * </p>
+ */
+@Mapper
+public interface KgCountTotalInfoMapper {
+    KgCountTotalInfo getCountTotalInfo();
+    
+    void save(KgCountTotalInfo info);
+    
+    void update(KgCountTotalInfo info);
+    
+    KgCountTotalInfo calculateTotalInfo();
+}

+ 59 - 0
src/main/java/com/qizhen/healsphere/repository/mapper/entity/KgCountInfo.java

@@ -0,0 +1,59 @@
+package com.qizhen.healsphere.repository.mapper.entity;
+
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 知识图谱统计信息
+ * </p>
+ */
+@Data
+public class KgCountInfo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 记录创建时间
+     */
+    private LocalDateTime gmtCreate;
+
+    /**
+     * 记录修改时间,如果时间是1970年则表示纪录未修改
+     */
+    private LocalDateTime gmtModified;
+
+    /**
+     * 实体类型
+     */
+    private String nodeType;
+
+    /**
+     * 实体数量
+     */
+    private Integer nodeNum;
+
+    /**
+     * 实体属性数量
+     */
+    private Integer nodePropNum;
+
+    /**
+     * 关系类型
+     */
+    private Integer relationType;
+
+    /**
+     * 关系数量
+     */
+    private Integer relationNum;
+
+}

+ 59 - 0
src/main/java/com/qizhen/healsphere/repository/mapper/entity/KgCountTotalInfo.java

@@ -0,0 +1,59 @@
+package com.qizhen.healsphere.repository.mapper.entity;
+
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 知识图谱统计信息
+ * </p>
+ */
+@Data
+public class KgCountTotalInfo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 记录创建时间
+     */
+    private LocalDateTime gmtCreate;
+
+    /**
+     * 记录修改时间,如果时间是1970年则表示纪录未修改
+     */
+    private LocalDateTime gmtModified;
+
+    /**
+     * 实体类型
+     */
+    private Integer nodeTypeNum;
+
+    /**
+     * 实体数量
+     */
+    private Integer nodeNum;
+
+    /**
+     * 实体属性数量
+     */
+    private Integer nodePropNum;
+
+    /**
+     * 关系类型
+     */
+    private Integer relationTypeNum;
+
+    /**
+     * 关系数量
+     */
+    private Integer relationNum;
+
+}

+ 23 - 0
src/main/java/com/qizhen/healsphere/service/KgCountService.java

@@ -0,0 +1,23 @@
+package com.qizhen.healsphere.service;
+
+import com.qizhen.healsphere.web.param.KgCountListPageQuery;
+import com.qizhen.healsphere.web.vo.CountInfoVO;
+import com.qizhen.healsphere.web.vo.CountListVO;
+import com.qizhen.healsphere.web.vo.Page;
+
+/**
+ * <p>
+ * 服务类
+ * </p>
+ *
+ * @author gaodm
+ * @since 2018-08-02
+ */
+public interface KgCountService {
+
+    CountInfoVO getCountTotalInfo();
+
+    Page<CountListVO> getCountListInfo(KgCountListPageQuery query);
+
+    Boolean updateStatisticsData();
+}

+ 161 - 0
src/main/java/com/qizhen/healsphere/service/impl/KgCountServiceImpl.java

@@ -0,0 +1,161 @@
+package com.qizhen.healsphere.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import com.qizhen.healsphere.repository.mapper.KgCountInfoMapper;
+import com.qizhen.healsphere.repository.mapper.KgCountTotalInfoMapper;
+import com.qizhen.healsphere.repository.mapper.entity.KgCountInfo;
+import com.qizhen.healsphere.repository.mapper.entity.KgCountTotalInfo;
+import com.qizhen.healsphere.service.KgCountService;
+import com.qizhen.healsphere.web.param.KgCountListPageQuery;
+import com.qizhen.healsphere.web.vo.CountInfoVO;
+import com.qizhen.healsphere.web.vo.CountListVO;
+import com.qizhen.healsphere.web.vo.Page;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p>
+ * 服务实现类
+ * </p>
+ */
+@Slf4j
+@Service
+public class KgCountServiceImpl implements KgCountService {
+
+    @Autowired
+    private KgCountTotalInfoMapper kgCountTotalInfoMapper;
+
+    @Autowired
+    private KgCountInfoMapper kgCountInfoMapper;
+
+    @Override
+    public CountInfoVO getCountTotalInfo() {
+
+        CountInfoVO countInfoVO = new CountInfoVO();
+        List<CountInfoVO.InfoVO> infoVOS = new ArrayList<>();
+        CountInfoVO.InfoVO nodeTypeInfoVO = new CountInfoVO.InfoVO();
+        nodeTypeInfoVO.setName("实体类型");
+        nodeTypeInfoVO.setNum(0);
+
+        CountInfoVO.InfoVO nodeInfoVO = new CountInfoVO.InfoVO();
+        nodeInfoVO.setName("实体");
+        nodeInfoVO.setNum(0);
+
+        CountInfoVO.InfoVO nodePropInfoVO = new CountInfoVO.InfoVO();
+        nodePropInfoVO.setName("实体属性");
+        nodePropInfoVO.setNum(0);
+
+        CountInfoVO.InfoVO relationTypeInfoVO = new CountInfoVO.InfoVO();
+        relationTypeInfoVO.setName("关系类型");
+        relationTypeInfoVO.setNum(0);
+
+        CountInfoVO.InfoVO relationInfoVO = new CountInfoVO.InfoVO();
+        relationInfoVO.setName("关系");
+        relationInfoVO.setNum(0);
+
+        KgCountTotalInfo countTotalInfo = kgCountTotalInfoMapper.getCountTotalInfo();
+        if (countTotalInfo != null) {
+            nodeTypeInfoVO.setNum(countTotalInfo.getNodeTypeNum());
+            nodeInfoVO.setNum(countTotalInfo.getNodeNum());
+            nodePropInfoVO.setNum(countTotalInfo.getNodePropNum());
+            relationTypeInfoVO.setNum(countTotalInfo.getRelationTypeNum());
+            relationInfoVO.setNum(countTotalInfo.getRelationNum());
+        }
+        infoVOS.add(nodeTypeInfoVO);
+        infoVOS.add(nodeInfoVO);
+        infoVOS.add(nodePropInfoVO);
+        infoVOS.add(relationTypeInfoVO);
+        infoVOS.add(relationInfoVO);
+        countInfoVO.setInfos(infoVOS);
+        return countInfoVO;
+    }
+
+    @Override
+    public Page<CountListVO> getCountListInfo(KgCountListPageQuery query) {
+        Integer pageNo = query.getPageNo();
+        Integer pageSize = query.getPageSize();
+
+        Integer count = kgCountInfoMapper.count();
+        List<CountListVO> listVOS = new ArrayList<>();
+        if (count > 0){
+            List<KgCountInfo> countList = kgCountInfoMapper.getCountList(pageSize, (pageNo - 1) * pageSize);
+            if (CollUtil.isNotEmpty(countList)){
+                countList.forEach(kgCountInfo -> {
+                    CountListVO countListVO = BeanUtil.copyProperties(kgCountInfo, CountListVO.class);
+                    listVOS.add(countListVO);
+                });
+            }
+        }
+        return new Page<>(pageNo,pageSize,listVOS.size(),count,listVOS);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean updateStatisticsData() {
+        try {
+            log.info("开始更新统计数据...");
+            
+            // 1. 更新总体统计信息
+            updateTotalInfo();
+            
+            // 2. 更新分类统计信息
+            updateDetailInfo();
+            
+            log.info("统计数据更新完成");
+            return true;
+        } catch (Exception e) {
+            log.error("更新统计数据失败", e);
+            throw new RuntimeException("更新统计数据失败", e);
+        }
+    }
+
+    private void updateTotalInfo() {
+        // 1. 获取新的统计数据
+        KgCountTotalInfo totalInfo = kgCountTotalInfoMapper.calculateTotalInfo();
+        if (totalInfo == null) {
+            throw new RuntimeException("计算总体统计数据失败");
+        }
+
+        // 2. 查询现有数据
+        KgCountTotalInfo existingInfo = kgCountTotalInfoMapper.getCountTotalInfo();
+
+        // 3. 更新或插入数据
+        if (existingInfo != null) {
+            totalInfo.setId(existingInfo.getId());
+            kgCountTotalInfoMapper.update(totalInfo);
+            log.info("更新总体统计数据成功");
+        } else {
+            totalInfo.setId(1L);
+            kgCountTotalInfoMapper.save(totalInfo);
+            log.info("插入总体统计数据成功");
+        }
+    }
+
+    private void updateDetailInfo() {
+        try {
+            // 1. 获取新的分类统计数据
+            List<KgCountInfo> detailInfoList = kgCountInfoMapper.calculateDetailInfo();
+            if (CollUtil.isEmpty(detailInfoList)) {
+                log.warn("没有获取到分类统计数据");
+                return;
+            }
+
+            // 2. 清空现有数据
+            kgCountInfoMapper.clearTable();
+            log.info("清空分类统计表成功");
+
+            // 3. 批量插入新数据
+            kgCountInfoMapper.batchInsert(detailInfoList);
+            log.info("插入分类统计数据成功,共 {} 条记录", detailInfoList.size());
+        } catch (Exception e) {
+            log.error("更新分类统计数据失败", e);
+            throw new RuntimeException("更新分类统计数据失败", e);
+        }
+    }
+}

+ 43 - 0
src/main/java/com/qizhen/healsphere/web/KgCountController.java

@@ -0,0 +1,43 @@
+package com.qizhen.healsphere.web;
+
+import com.qizhen.healsphere.service.KgCountService;
+import com.qizhen.healsphere.web.dto.RespDTO;
+import com.qizhen.healsphere.web.param.KgCountListPageQuery;
+import com.qizhen.healsphere.web.vo.CountInfoVO;
+import com.qizhen.healsphere.web.vo.CountListVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+@RequestMapping("/kg/count")
+@Api(value = "知识图谱统计API", tags = { "知识图谱统计API" })
+@SuppressWarnings("unchecked")
+@Slf4j
+public class KgCountController {
+
+    @Autowired
+    private KgCountService kgCountService;
+
+    @ApiOperation(value = "获取统计信息", notes = "获取统计信息")
+    @RequestMapping(value = "/getCountInfo", method = RequestMethod.POST)
+    @ResponseBody
+    public RespDTO<CountInfoVO> getCountInfo() {
+        return RespDTO.onSuc(kgCountService.getCountTotalInfo());
+    }
+
+    @ApiOperation(value = "获取统计列表")
+    @RequestMapping(value = "/getCountList", method = RequestMethod.POST)
+    @ResponseBody
+    public RespDTO<Page<CountListVO>> getCountList(@RequestBody KgCountListPageQuery query) {
+        return RespDTO.onSuc(kgCountService.getCountListInfo(query));
+    }
+}
+

+ 30 - 0
src/main/java/com/qizhen/healsphere/web/KgCountImportDataController.java

@@ -0,0 +1,30 @@
+package com.qizhen.healsphere.web;
+
+import com.qizhen.healsphere.service.KgCountService;
+import com.qizhen.healsphere.web.dto.RespDTO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+@RequestMapping("/kg/import")
+@Api(value = "知识图谱统计数据导入API", tags = { "知识图谱统计数据导入API" })
+@Slf4j
+public class KgCountImportDataController {
+
+    @Autowired
+    private KgCountService kgCountService;
+
+    @ApiOperation(value = "更新统计数据", notes = "更新统计数据")
+    @RequestMapping(value = "/updateData", method = RequestMethod.POST)
+    @ResponseBody
+    public RespDTO<Boolean> updateData() {
+        return RespDTO.onSuc(kgCountService.updateStatisticsData());
+    }
+}
+

+ 18 - 0
src/main/java/com/qizhen/healsphere/web/param/KgCountListPageQuery.java

@@ -0,0 +1,18 @@
+package com.qizhen.healsphere.web.param;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+@Data
+@ApiModel("分页参数")
+public class KgCountListPageQuery {
+    @NotNull(message = "分页信息不能为空")
+    @ApiModelProperty(value = "当前页码", required = true)
+    private Integer pageNo;
+    @NotNull(message = "分页信息不能为空")
+    @ApiModelProperty(value = "每页条数", required = true)
+    private Integer pageSize;
+}

+ 16 - 0
src/main/java/com/qizhen/healsphere/web/vo/CountInfoVO.java

@@ -0,0 +1,16 @@
+package com.qizhen.healsphere.web.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class CountInfoVO {
+    private List<InfoVO> infos;
+
+    @Data
+    public static class InfoVO{
+        private String name;
+        private Integer num;
+    }
+}

+ 12 - 0
src/main/java/com/qizhen/healsphere/web/vo/CountListVO.java

@@ -0,0 +1,12 @@
+package com.qizhen.healsphere.web.vo;
+
+import lombok.Data;
+
+@Data
+public class CountListVO {
+    private String nodeType;
+    private Integer nodeNum;
+    private Integer nodePropNum;
+    private Integer relationType;
+    private Integer relationNum;
+}

+ 37 - 0
src/main/java/com/qizhen/healsphere/web/vo/Page.java

@@ -0,0 +1,37 @@
+package com.qizhen.healsphere.web.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class Page<T> {
+    private int pageNumber;
+
+    // 每页显示的记录数
+    private int pageSize;
+
+    // 当前页包含的记录总数
+    private int numberOfElements;
+
+    // 总记录数
+    private long totalElements;
+
+    // 总页数
+    private int totalPages;
+
+    // 当前页包含的记录列表
+    private List<T> content;
+
+    // 构造方法、getter和setter方法
+
+    public Page(int pageNumber, int pageSize, int numberOfElements, long totalElements, List<T> content) {
+        this.pageNumber = pageNumber;
+        this.pageSize = pageSize;
+        this.numberOfElements = numberOfElements;
+        this.totalElements = totalElements;
+        this.content = content;
+        // 计算总页数
+        this.totalPages = (int) Math.ceil((double) totalElements / pageSize);
+    }
+}

+ 9 - 4
src/main/resources/application-local.yml

@@ -4,10 +4,15 @@ swagger:
 spring:
   datasource:
     hikari:
-      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!@#
+      jdbc-url: jdbc:postgresql://172.16.8.59:5433/postgres
+      driver-class-name: org.postgresql.Driver
+      username: postgres
+      password: 1Qaz@wsx
+#      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!@#
+
   neo4j:
 #    uri: bolt://172.16.8.59:7687
 #    authentication:

+ 88 - 0
src/main/resources/mapper/mysql/KgCountInfoMapper.xml

@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.qizhen.healsphere.repository.mapper.KgCountInfoMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.qizhen.healsphere.repository.mapper.entity.KgCountInfo">
+        <id column="id" property="id" />
+        <result column="gmt_create" property="gmtCreate" />
+        <result column="gmt_modified" property="gmtModified" />
+        <result column="node_type" property="nodeType" />
+        <result column="node_num" property="nodeNum" />
+        <result column="node_prop_num" property="nodePropNum" />
+        <result column="relation_type" property="relationType" />
+        <result column="relation_num" property="relationNum" />
+    </resultMap>
+
+    <select id="getCountList" resultMap="BaseResultMap">
+        select * from kg_count_info limit #{pageSize} offset #{offset}
+    </select>
+
+    <select id="count" resultType="java.lang.Integer">
+        select count(*) from kg_count_info
+    </select>
+
+    <!-- 按照节点类型统计详细信息 -->
+    <select id="calculateDetailInfo" resultMap="BaseResultMap">
+        SELECT 
+            n.category as node_type,
+            COUNT(DISTINCT n.id) as node_num,
+            COALESCE(SUM(prop_counts.prop_num), 0) as node_prop_num,
+            COUNT(DISTINCT edge_counts.type) as relation_type,
+            COALESCE(SUM(edge_counts.relation_count), 0) as relation_num
+        FROM kg_nodes n
+        LEFT JOIN (
+            SELECT 
+                ref_id,
+                COUNT(*) as prop_num
+            FROM kg_props
+            GROUP BY ref_id
+        ) prop_counts ON n.id = prop_counts.ref_id
+        LEFT JOIN (
+            SELECT 
+                src_id as node_id,
+                name as type,
+                COUNT(*) as relation_count
+            FROM kg_edges
+            GROUP BY src_id, name
+            UNION ALL
+            SELECT 
+                dest_id as node_id,
+                name as type,
+                COUNT(*) as relation_count
+            FROM kg_edges
+            GROUP BY dest_id, name
+        ) edge_counts ON n.id = edge_counts.node_id
+        GROUP BY n.category
+    </select>
+
+    <!-- 清空统计表 -->
+    <delete id="clearTable">
+        DELETE FROM kg_count_info
+    </delete>
+
+    <!-- 批量插入统计数据 -->
+    <insert id="batchInsert" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="id">
+        INSERT INTO kg_count_info (
+            gmt_create,
+            gmt_modified,
+            node_type,
+            node_num,
+            node_prop_num,
+            relation_type,
+            relation_num
+        ) VALUES 
+        <foreach collection="list" item="item" separator=",">
+            (
+                now(),
+                now(),
+                #{item.nodeType},
+                #{item.nodeNum},
+                #{item.nodePropNum},
+                #{item.relationType},
+                #{item.relationNum}
+            )
+        </foreach>
+    </insert>
+
+</mapper>

+ 81 - 0
src/main/resources/mapper/mysql/KgCountTotalInfoMapper.xml

@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.qizhen.healsphere.repository.mapper.KgCountTotalInfoMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.qizhen.healsphere.repository.mapper.entity.KgCountTotalInfo">
+        <id column="id" property="id" />
+        <result column="gmt_create" property="gmtCreate" />
+        <result column="gmt_modified" property="gmtModified" />
+        <result column="node_type_num" property="nodeTypeNum" />
+        <result column="node_num" property="nodeNum" />
+        <result column="node_prop_num" property="nodePropNum" />
+        <result column="relation_type_num" property="relationTypeNum" />
+        <result column="relation_num" property="relationNum" />
+    </resultMap>
+
+    <select id="getCountTotalInfo" resultMap="BaseResultMap">
+        select * from kg_count_total_info limit 1
+    </select>
+
+    <insert id="save" parameterType="com.qizhen.healsphere.repository.mapper.entity.KgCountTotalInfo" 
+            useGeneratedKeys="true" keyProperty="id">
+        insert into kg_count_total_info (
+            id,
+            gmt_create,
+            gmt_modified,
+            node_type_num,
+            node_num,
+            node_prop_num,
+            relation_type_num,
+            relation_num
+        ) values (
+            1,  <!-- 由于只有一条记录,直接使用固定值 1 -->
+            now(),
+            now(),
+            #{nodeTypeNum},
+            #{nodeNum},
+            #{nodePropNum},
+            #{relationTypeNum},
+            #{relationNum}
+        )
+    </insert>
+
+    <update id="update" parameterType="com.qizhen.healsphere.repository.mapper.entity.KgCountTotalInfo">
+        update kg_count_total_info
+        set gmt_modified = now(),
+            node_type_num = #{nodeTypeNum},
+            node_num = #{nodeNum},
+            node_prop_num = #{nodePropNum},
+            relation_type_num = #{relationTypeNum},
+            relation_num = #{relationNum}
+        where id = #{id}
+    </update>
+
+    <!-- 统计所有节点和关系的汇总信息 -->
+    <select id="calculateTotalInfo" resultMap="BaseResultMap">
+        SELECT 
+            t1.node_type_num,
+            t1.node_num,
+            t2.node_prop_num,
+            t3.relation_type_num,
+            t3.relation_num
+        FROM (
+            SELECT 
+                COUNT(DISTINCT category) as node_type_num,
+                COUNT(*) as node_num 
+            FROM kg_nodes
+        ) t1,
+        (
+            SELECT COUNT(*) as node_prop_num 
+            FROM kg_props
+        ) t2,
+        (
+            SELECT 
+                COUNT(DISTINCT name) as relation_type_num,
+                COUNT(*) as relation_num 
+            FROM kg_edges
+        ) t3
+    </select>
+
+</mapper>