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

Delete Query在SQLYog中生效但Java应用中执行无效果的问题

问题:Java执行带DATE类型复合主键的DELETE语句返回0受影响行(手动执行SQL正常)

场景说明

数据库表prod_evidencija以idProdavac、idProdavnica(外键)和datum(DATE类型)作为复合主键,对应Java关联类prod_evidencija中的datum为LocalDate类型。

Java中编写的DELETE逻辑打印出的SQL语句手动在SQLYog执行可成功删除数据,但通过PreparedStatement执行时返回0受影响行数,无任何异常。该删除方法对其他无日期类型的对象正常工作,且该表的Insert、Update操作也能正常执行。

相关代码

关联类的DELETE查询与参数填充

@Override
public String getDeleteQuery() {
    return "DELETE FROM prod_evidencija WHERE idProdavac = ? AND idProdavnica = ? AND datum = ?";
}

@Override
public void fillDeleteStatement(PreparedStatement ps) throws SQLException {
   ps.setInt(1, prodavac.getIdProdavac());
   ps.setInt(2, prodavnica.getIdProdavnica());
   ps.setDate(3, java.sql.Date.valueOf(datum));
   // 曾尝试ps.setObject(3, datum);无效
    System.out.println(datum); // 输出示例:2022-07-24
}

数据库代理的delete方法

public <T extends DomainObject<T>> Object delete(T obj) throws SQLException {
    try (PreparedStatement ps = Konekcija.getInstance().getKonekcija()
            .prepareStatement(obj.getDeleteQuery())) {
        obj.fillDeleteStatement(ps);
        System.out.println(ps); // 打印出的SQL示例:DELETE FROM prod_evidencija WHERE idProdavac = 1 AND idProdavnica = 2 AND datum = '2026-05-11'
        int affectedRows = ps.executeUpdate();
        System.out.println(affectedRows); // 输出0
        return affectedRows > 0;
    }
}

排查与解决方案

1. 检查Java与数据库的时区一致性

这是最常见的原因:Java应用的时区和数据库服务器时区不匹配,导致LocalDate转换为java.sql.Date后,实际传入数据库的日期和存储的日期存在隐性差异(比如UTC时区的2022-07-24转换为东八区可能是2022-07-23)。

解决措施:

  • 统一两者时区:JVM启动时添加参数-Duser.timezone=UTC,同时将数据库时区设置为UTC(以MySQL为例,修改my.cnf中的default-time-zone = '+00:00')。
  • 或者在JDBC连接URL中指定时区,比如MySQL的URL添加?serverTimezone=UTC。

2. 查看数据库实际执行的参数

虽然打印出的PreparedStatement显示日期正确,但实际绑定的参数可能存在转换问题。开启数据库的查询日志,查看Java执行时的真实参数:

  • MySQL:开启general_log,日志中会记录执行的完整SQL及参数值,对比手动执行的参数是否一致。
  • 其他数据库:对应开启查询审计日志。

3. 临时用字符串绑定日期排查

将LocalDate格式化为数据库兼容的字符串,替换日期参数绑定方式,验证是否为类型转换问题:

@Override
public void fillDeleteStatement(PreparedStatement ps) throws SQLException {
   ps.setInt(1, prodavac.getIdProdavac());
   ps.setInt(2, prodavnica.getIdProdavnica());
   // 用ISO格式字符串绑定
   ps.setString(3, datum.format(DateTimeFormatter.ISO_LOCAL_DATE));
}

如果此方式能成功删除,说明是日期类型转换的问题,再针对性解决时区或驱动版本问题。

4. 升级JDBC驱动版本

旧版本的JDBC驱动对LocalDate转java.sql.Date的支持可能存在bug,比如MySQL Connector/J 5.x的某些版本,升级到最新稳定版(如8.x)即可修复。

5. 确认对象中datum值的准确性

再次确认prod_evidencija对象中的datum值是否与数据库中存在的记录完全一致,比如是否存在拼写错误、格式差异(虽然打印显示正确,但可通过debug确认对象的实际值)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 23:48:10