个人技术博客——Spring Data JPA

222200330徐林熙 2024-12-20 21:48:23
这个作业属于哪个课程 FZU_SE_teacherW_4社区
这个作业要求在哪里软件工程实践总结&个人技术博客
这个作业的目标个人技术总结
其他参考文献Spring Data JPA 官方文档MySQL 官方文档

目录

  • 技术概述
  • 学习原因
  • 技术难点
  • 技术详述
  • 1. 获取用户最新健康报告
  • 数据库表设计
  • 接口定义
  • Service 层实现
  • Controller 实现
  • 2. 创建健康报告
  • 数据库查询
  • Service 层保存报告
  • 遇到的问题与解决方案
  • 问题 1:Spring Data JPA 查询返回值为空
  • 问题 2:健康数据表字段映射异常
  • 问题 3:数据库连接超时
  • 总结

技术概述

在团队开发中,我主要负责健康报告管理系统的后端服务设计与实现。整个项目基于 Spring Boot 构建,其中一项关键技术是基于 Spring Data JPA 的动态查询与数据持久化

Spring Data JPA 提供了高效、简洁的数据库操作方式,尤其适合处理复杂数据查询与事务管理。它通过定义接口自动实现常见的数据库操作,能够大幅减少样板代码的编写。

学习原因

选择学习 Spring Data JPA 的原因在于:

  1. 它可以快速开发 CRUD 操作。
  2. 它支持复杂查询,减少原生 SQL 编写。
  3. 它与 Spring Boot 无缝集成。

技术难点

  1. 复杂动态查询的构造,例如基于多条件排序与筛选。
  2. 数据库事务管理与异常处理。
  3. 理解实体映射注解及其与数据库表的对应关系。

技术详述

1. 获取用户最新健康报告

在健康报告管理模块中,需要实现查询某个用户最新的健康报告功能。这通过 Spring Data JPA 的自定义查询完成。

数据库表设计

健康报告表 (health_report) 结构如下:

字段名类型描述
report_idVARCHAR(32)健康报告 ID
user_idVARCHAR(32)用户 ID
report_typeVARCHAR(50)报告类型
report_dateDATE报告生成日期
contentTEXT报告内容
suggestionsTEXT建议
created_atTIMESTAMP创建时间
updated_atTIMESTAMP更新时间

接口定义

HealthReportRepository.java 中定义自定义查询方法:

@Repository
public interface HealthReportRepository extends JpaRepository<HealthReport, String> {

    // 查找某个用户的最新健康报告
    Optional<HealthReport> findTopByUserIdOrderByReportDateDesc(String userId);
}
  • findTopByUserIdOrderByReportDateDesc:根据 userId 查找最新的健康报告(按 report_date 降序)。
  • Optional 用于防止返回值为空时导致的空指针异常。

Service 层实现

通过 HealthReportRepository 调用查询方法:

@Service
public class HealthReportService {

    @Autowired
    private HealthReportRepository healthReportRepository;

    public HealthReport getLatestReportByUserId(String userId) {
        // 使用 findTopByUserIdOrderByReportDateDesc 查询最新报告
        Optional<HealthReport> report = healthReportRepository.findTopByUserIdOrderByReportDateDesc(userId);
        return report.orElse(null);  // 如果没有报告,返回 null
    }
}

Controller 实现

HealthReportController 中,暴露 RESTful 接口:

@RestController
public class HealthReportController {

    @Autowired
    private HealthReportService healthReportService;

    @GetMapping("/healthReportDetail")
    public String getHealthReportDetail(@RequestParam("userId") String userId, Model model) {
        HealthReport report = healthReportService.getLatestReportByUserId(userId);
        if (report != null) {
            model.addAttribute("report", report);
        } else {
            model.addAttribute("error", "没有找到健康报告");
        }
        return "healthReportDetail";  // 返回视图 healthReportDetail.html
    }
}

2. 创建健康报告

为了自动生成健康报告,我们从健康数据表 (health_data) 中获取用户的最新健康数据。

数据库查询

HealthData 实体中定义静态方法,通过原生 SQL 查询健康数据:

public static HealthData getLatestHealthData(String userId) {
    HealthData healthData = null;
    String query = "SELECT * FROM health_data WHERE user_id = ? ORDER BY record_date DESC LIMIT 1";

    try (Connection conn = DatabaseConnection.getConnection();
         PreparedStatement stmt = conn.prepareStatement(query)) {

        stmt.setString(1, userId);
        ResultSet rs = stmt.executeQuery();
        if (rs.next()) {
            healthData = new HealthData();
            healthData.healthId = rs.getString("health_id");
            healthData.userId = rs.getString("user_id");
            healthData.recordDate = rs.getDate("record_date");
            healthData.sleepDuration = rs.getInt("sleep_duration");
            healthData.heartRate = rs.getInt("heart_rate");
            healthData.bloodPressure = rs.getString("blood_pressure");
            healthData.steps = rs.getInt("steps");
            healthData.calories = rs.getDouble("calories");
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }

    return healthData;
}

Service 层保存报告

通过获取健康数据生成建议,并保存到报告表中:

@Service
public class HealthReportService {

    public HealthReport createAndSaveHealthReport(String userId, String reportType, String content, String suggestions) {
        HealthReport report = new HealthReport();
        report.setUserId(userId);
        report.setReportType(reportType);
        report.setContent(content);
        report.setSuggestions(suggestions);
        report.setReportDate(new Date());

        healthReportRepository.save(report);
        return report;
    }
}

遇到的问题与解决方案

问题 1:Spring Data JPA 查询返回值为空

  • 原因:当数据库中不存在符合条件的数据时,findTopByUserIdOrderByReportDateDesc 返回 Optional.empty()
  • 解决方案:在 Service 层处理空值逻辑,通过 orElse(null) 避免空指针异常。

问题 2:健康数据表字段映射异常

  • 原因:实体类中的字段与数据库表字段名称不一致。
  • 解决方案
    1. 使用 @Column 显式指定字段映射关系。
    2. 检查表字段是否正确创建。

问题 3:数据库连接超时

  • 原因:JDBC 连接池配置不足,导致高并发时连接不足。
  • 解决方案:使用 HikariCP 数据源优化连接池配置,例如增加最大连接数。示例配置:
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.max-lifetime=1800000

总结

通过本次开发实践,我深入掌握了 Spring Data JPA 的查询与数据持久化技巧,同时在健康报告生成与健康数据查询方面积累了实战经验。这些技术为团队项目提供了可靠的数据管理基础,也提升了开发效率。


...全文
57 回复 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

239

社区成员

发帖
与我相关
我的任务
社区管理员
  • FZU_SE_teacherW
  • 助教赖晋松
  • D's Honey
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧