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

H2数据库报错JdbcSQLSyntaxErrorException: SPORTEVENT表不存在排查

问题根因

抛出Table "SPORTEVENT" not found错误是多个问题叠加导致的,和单独加DB_CLOSE_DELAY=-1参数没有直接关系:

  • 核心问题:代码中从未执行过建表逻辑。H2内存数据库启动后默认是空库,不会自动创建业务表,现有代码只有插入数据的逻辑,没有创建SPORTEVENT表的步骤,自然找不到对应表。
  • 连接配置错误:JDBC URL拼接逻辑完全不符合H2规范。一方面实例化连接类时传入的databaseName参数已经重复带了jdbc:h2:mem:前缀,最终拼接出的URL是无效的jdbc:h2:mem://localhost/jdbc:h2:mem:sports_betting;另一方面H2内存模式是JVM进程内数据库,不需要写//localhost/主机段,该格式是H2 TCP服务模式的写法。
  • 附带逻辑错误:插入SQL的参数和字段不匹配。INSERT语句定义了6个字段,但代码中漏了TITLE字段的赋值,参数序号错位,就算表存在也会抛出参数不匹配异常;同时new Date(2022-07-06)是语法错误,2022-07-06会被当成算术表达式计算为整数,生成的日期完全不符合预期。
修复步骤

按顺序修改以下代码即可解决问题:

  1. 修正数据库连接配置
    首先修改DatabaseConnectionManager的构造方法,调整URL拼接规则,加上内存库持久化参数:
    public DatabaseConnectionManager(String databaseName, String username,String password){
        // H2内存库正确URL格式,不需要主机段,加上DB_CLOSE_DELAY=-1防止连接关闭后库被清空
        this.url = "jdbc:h2:mem:"+databaseName+";DB_CLOSE_DELAY=-1";
        this.properties = new Properties();
        this.properties.setProperty("username",username);
        this.properties.setProperty("password",password);
    }
    
    对应修改JDBCExecutor中的连接实例化代码,不要重复传入JDBC前缀,只传库名即可:
    DatabaseConnectionManager databaseConnectionManager= new DatabaseConnectionManager("sports_betting","sa","");
    
  2. 补充建表逻辑
    获取数据库连接后,在执行插入操作前先执行建表语句,避免表不存在:
    Connection connection = databaseConnectionManager.getConnection();
    // 新增建表逻辑,表不存在时才创建
    try(Statement stmt = connection.createStatement()){
        stmt.execute("CREATE TABLE IF NOT EXISTS SPORTEVENT (" +
                "DTYPE VARCHAR(50) NOT NULL," +
                "ID INT PRIMARY KEY," +
                "START DATE," +
                "END DATE," +
                "TITLE VARCHAR(255)," +
                "RESULT_ID INT" +
                ")");
    }
    
  3. 修正插入逻辑和日期创建错误
    首先修改SporteventDAO的create方法,补全缺失的TITLE参数赋值,修正参数序号:
    @Override
    public FootballSportEvent create(FootballSportEvent dto) throws SQLException {
        try(PreparedStatement statement = this.connection.prepareStatement(INSERT);){
            statement.setString(1,dto.getType());
            statement.setInt(2,dto.getId());
            statement.setDate(3, (Date) dto.getStart());
            statement.setDate(4, (Date) dto.getEnd());
            statement.setString(5, dto.getTitle()); // 补全之前缺失的TITLE字段赋值
            statement.setInt(6, dto.getResultId()); // 修正参数序号,原代码错写为5
            statement.execute();
        }catch (SQLException e){
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        return dto;
    }
    
    然后修正JDBCExecutor中的日期创建错误,给title字段赋值:
    // 用Date.valueOf生成合法的java.sql.Date对象,不要直接传算术表达式
    Date start = Date.valueOf("2022-07-06");
    Date end = Date.valueOf("2022-07-07");
    footballSportEvent.setStart(start);
    footballSportEvent.setEnd(end);
    footballSportEvent.setResultId(2);
    footballSportEvent.setTitle("测试足球赛事"); // 给title字段赋值
    

补充:如果不想每次启动手动写建表逻辑,也可以在项目resources目录下创建schema.sql文件,把建表语句写在文件中,H2启动时会自动执行该脚本完成表初始化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 14:03:18