You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java操作MySQL更新表前判断指定日期是否存在的问题求解

问题排查与解决

两个版本的核心问题

第一版代码问题

  • COUNT聚合查询无论有没有匹配记录,都会返回一行结果,所以rs.next()永远返回true,!rs.next()永远为false,逻辑完全和实际是否存在数据无关。

第二版代码问题

  • MySQL JDBC默认返回的ResultSet是TYPE_FORWARD_ONLY类型,仅支持顺序向下遍历,调用rs.first()会直接抛出SQLException,你代码中只在catch里打印错误没有做业务处理,异常触发后直接跳过插入逻辑,执行后续的重定向返回,所以永远不会触发插入操作。

正确实现方案

方案1:修复现有JDBC逻辑

修改ResultSet读取部分的代码,同时补全资源自动关闭逻辑,代码如下:

@PostMapping("/add")
public Object processMenuAddForm(@ModelAttribute @Valid Menu menu, Errors errors, HttpServletRequest request,
                                 Model model)
        throws ParseException, SQLException {

    User user = getUserFromSession(request.getSession());

    if (errors.hasErrors()) {
        model.addAttribute("title", "Add");
        return "/menu/add";
    }
    // Connection也放进try-with-resources自动关闭,避免连接泄漏
    try (Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/family_organizer",
            "family_organizer", "LiftOff2021");
         PreparedStatement checkDateExists = con.prepareStatement(
                 "SELECT COUNT(date) AS count FROM menu WHERE user_id = ? AND date = ?")) {
        checkDateExists.setInt(1, user.getId());
        checkDateExists.setString(2, menu.getDate());

        try (ResultSet rs = checkDateExists.executeQuery()) {
            // 去掉rs.first(),COUNT查询一定有一行,直接调用rs.next()移动指针到第一行即可
            if (rs.next() && rs.getInt("count") == 0) {
                Menu newMenu = new Menu(menu.getDate(), menu.getMainCourse(), menu.getVegetable(), menu.getMainSide(),
                        menu.getAdditionalSide(), menu.getDessert(), user);
                menuRepository.save(newMenu);
            }
        } catch (SQLException err) {
            // 建议打印完整堆栈方便排查,不要只打印错误信息
            err.printStackTrace();
        }
        return "redirect:/menu/view";
    }
}

方案2:更符合Spring生态的实现(推荐)

你已经使用了Spring Data JPA的menuRepository,完全不需要自己手写JDBC代码,直接在Repository接口中添加统计方法即可:

  1. 给MenuRepository添加查询方法:
public interface MenuRepository extends JpaRepository<Menu, Integer> {
    long countByUserIdAndDate(Integer userId, String date);
}
  1. 简化业务层代码:
@PostMapping("/add")
public Object processMenuAddForm(@ModelAttribute @Valid Menu menu, Errors errors, HttpServletRequest request,
                                 Model model) {
    User user = getUserFromSession(request.getSession());
    if (errors.hasErrors()) {
        model.addAttribute("title", "Add");
        return "/menu/add";
    }
    if (menuRepository.countByUserIdAndDate(user.getId(), menu.getDate()) == 0) {
        Menu newMenu = new Menu(menu.getDate(), menu.getMainCourse(), menu.getVegetable(), menu.getMainSide(),
                menu.getAdditionalSide(), menu.getDessert(), user);
        menuRepository.save(newMenu);
    }
    return "redirect:/menu/view";
}

额外优化建议

  • 可以直接给menu表添加user_id + date的唯一联合索引,数据库层面即可避免重复数据插入,业务代码可补充唯一索引冲突的处理逻辑,实现双重保障。
  • 不要硬编码数据库连接配置,放到Spring的application配置文件中,通过DataSource注入获取连接,更易维护也能避免连接泄漏。

内容的提问来源于stack exchange,提问作者Coder2021

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 02:27:03