h2错误提示:Table not found

时间:2022-09-11 14:45:01

问题

使用h2做内存数据库时,查询某表,程序提示table不存在。

引用h2版本

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.196</version>
</dependency>

启动数据库

public static void startH2Server() {
    try {
        System.out.println("正在启动h2数据库...");
        Server.createTcpServer().start();
        System.out.println("h2数据库启动成功...");
    } catch (SQLException e) {
        System.out.println("启动h2数据库出错:" + e.toString());
        e.printStackTrace();
        throw new RuntimeException(e);
    }
}

初始化数据库

private static final String JDBC_URL = "jdbc:h2:tcp://localhost/mem:gacl";
private static final String USER = "gacl";//用户名
private static final String PASSWORD = "123";//密码

public static void initTables() {
    Connection conn = null;
    Statement stmt = null;
    try {
        String sql = "......";//初始化数据SQL
        Class.forName(DRIVER_CLASS);
        conn = DriverManager.getConnection(JDBC_URL, USER, PASSWORD);
        stmt = conn.createStatement();
        stmt.execute(sql);
        sql = "SELECT COUNT(1) FROM xxxxxx";
        rs = stmt.executeQuery(sql);
        while (rs.next()) {
            System.out.print(" count:%s", rs.getInt(1));
        }
        System.out.println("初始化H2数据库数据完成!");
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (null != stmt) {
                stmt.close();
            }
            if (null != conn) {
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

查询数据库

public static List<Object> query(Map<String, String> params) {
    Connection conn = null;
    Statement stmt = null;
    List<Object> list = new ArrayList<Object>();
    try {
        Class.forName(DRIVER_CLASS);
        conn = DriverManager.getConnection(JDBC_URL, USER, PASSWORD);
        stmt = conn.createStatement();
        String sql = "SELECT ......";//查询SQL
        ResultSet rs = stmt.executeQuery(sql);
        while (rs.next()) {
            //处理rs
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (null != stmt) {
                stmt.close();
            }
            if (null != conn) {
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    return list;
}

但是在使用此查询时,总是提示查询的table不存在。

org.h2.jdbc.JdbcSQLException: Table “xxxxxx” not found; SQL statement:…….

明明在初始化数据库时,使用count方法能查询到值,怎么单独查询,却又找不到table了呢!

首先怀疑是SQL拼写错误,将查询SQL,放入“初始化方法”中执行,也可以出查询结果,说明查询用的SQL是没有写错。

但是单独执行时,一直提示找不到table,这就真奇怪了~

解决

在官方网站:http://www.h2database.com/html/features.html#in_memory_databases找到这么一段话,感觉有了新的希望。

By default, closing the last connection to a database closes the database. 
For an in-memory database, this means the content is lost. 
To keep the database open, add ;DB_CLOSE_DELAY=-1 to the database URL. 
To keep the content of an in-memory database as long as the virtual machine is alive,
use jdbc:h2:mem:test;DB_CLOSE_DELAY=-1.

大意就是关闭最后一个conn时,就关闭了database。如果要保持database 打开可用,需要的数据库URL中添加参数:;DB_CLOSE_DELAY=-1。

看来是因为在数据库初始化的finally中将conn关闭,导致关闭了database。所以再执行单独的查询SQL时,因为database已经关闭,所以才会提示找不到table。

将JDBC_URL修改为:

private static final String JDBC_URL = "jdbc:h2:tcp://localhost/mem:gacl;DB_CLOSE_DELAY=-1";

问题解决。