未在 H2 数据库上执行的 Sql 查询

Posted

技术标签:

【中文标题】未在 H2 数据库上执行的 Sql 查询【英文标题】:Sql queries not executed on H2 database 【发布时间】:2015-08-03 23:09:06 【问题描述】:

最近我从 HSQLDB 更改为 H2,更改了一些代码,我的查询停止执行。

我用 RazorSQL 测试我的 SQL 代码,我尝试从中访问我的数据库,令我惊讶的是没有创建表,没有抛出错误没有空指针,有效的 sql,db 文件创建 - 一切似乎都运行正常数据库中没有任何内容。

这是我的数据库访问/创建的关键部分。

我使用连接器类创建连接到数据库

public class H2DatabaseConnector 

    private Connection connection;
    private Statement statement;
    private ResultSet resultSet;


    public static final String[] PREP_STATEMENTS = new String[];

    public static final String DB_FILE_NAME = File.separator + "dboc";
    public static final String DB_DIR = Info.OC_DIR + "oc_database\\";

    static 
        try 
            Class.forName("org.h2.Driver");
         catch (ClassNotFoundException ex) 
            ex.printStackTrace();
        
    

    public H2DatabaseConnector(String username, String password) 
        try 
            openConnection(username, password);
         catch (SQLException ex) 
            ex.printStackTrace();
        
    

.....
//data credentials are correct
 private void openConnection(String username, String password) throws SQLException 
        connection = DriverManager.getConnection("jdbc:h2:file:" + DB_DIR + DB_FILE_NAME+";DATABASE_TO_UPPER=false", username, password);
        statement = connection.createStatement();
    

  public void execute() 
    


以及我执行 sql 命令的实用程序类

public class DbUtil 


    public static final void createUsersTable()
         new H2DatabaseConnector(Info.Db.DB_MAIN_USERNAME,Info.Db.DB_MAIN_PASSWORD) 

            @Override
            public void execute() 
                try 
                    getStatement().execute("CREATE TABLE users(name VARCHAR(255) NOT NULL,password VARCHAR(255) NOT NULL,email VARCHAR(255));");
                    System.out.println("Table Created users");
                    getStatement().executeUpdate("INSERT INTO users VALUES ('sa','sa',NULL);");
                    closeConnection();
                 catch (SQLException ex) 
                    ex.printStackTrace();
                
            

        .execute();
     


按预期执行,但未创建表。 为什么会这样?没有显示错误,并且 sql 语法是正确的,因为当我在 **RazorSQL 中打开数据库并创建/插入表时,一切正常。**

有什么想法吗?我真的坚持了一整天。

【问题讨论】:

您是否尝试过先提交事务?我不确定executeUpdate 应该与create table 一起使用... @MadProgrammer 先提交事务是什么意思? --btw--我使用了 execute(query) -edited now / Connection#commit 或将autoCommit 设置为true...? @MadProgrammer 将尝试 --- 不工作(错误:未找到表“USERS”;SQL 语句:) 在尝试从应用程序外部访问它之后。- 没有创建与以前相同的表 您可以尝试从您的 SQL 文字中删除分号 (;),即getStatement().execute("CREATE TABLE users(name VARCHAR(255) NOT NULL,password VARCHAR(255) NOT NULL,email VARCHAR(255))");吗? 【参考方案1】:

重复使用 Statement 可能会给您带来问题,但由于我没有完全可运行的示例,因此很难确定...

所以,我做了这个非常快速的测试(使用 1.4.182)...

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;

public class Test 

    public static void main(String[] args) 
        try 
            Class.forName("org.h2.Driver");
            try (Connection con = DriverManager.getConnection("jdbc:h2:file:./Test;DATABASE_TO_UPPER=false", "sa", "sa")) 

                try (Statement stmt = con.createStatement()) 
                    stmt.execute("CREATE TABLE if not exists users(name VARCHAR(255) NOT NULL,password VARCHAR(255) NOT NULL,email VARCHAR(255))");
                    con.commit();
                

                try (PreparedStatement stmt = con.prepareStatement("INSERT INTO users (name, password, email) VALUES (?,?,?)")) 
                    stmt.setString(1, "sa");
                    stmt.setString(2, "sa");
                    stmt.setString(3, null);
                    int rows = stmt.executeUpdate();
                    System.out.println(rows + " where inserted");
                    con.commit();
                

                try (PreparedStatement stmt = con.prepareStatement("select * from users")) 
                    try (ResultSet rs = stmt.executeQuery()) 
                        while (rs.next()) 
                            String name = rs.getString(1);
                            String password = rs.getString(2);
                            String email = rs.getString(3);
                            System.out.println(name + "; " + password + "; " + email);
                        
                    
                
            
         catch (Exception ex) 
            ex.printStackTrace();
        
    


第一次运行时输出...

1 where inserted
sa; sa; null

第二次运行时输出...

1 where inserted
sa; sa; null
sa; sa; null

就我个人而言,我会将每个 Statement 隔离到一个任务中,事实上,我也倾向于将每个 Connection 隔离,但那是因为我偏执;)

【讨论】:

将尝试根据您的示例修改我的代码/还添加/并会看到会发生什么,我会尽快发布输出 我还认为全局 Statement 变量可能会造成问题(H2 驱动程序甚至可能有一个微妙的错误,当语句被重用时会出现)。这个答案有很多好东西,OP 肯定应该在他的代码中包含:try-with-resources,最小化变量的范围,明确地提供列列表INSERTCREATE TABLE if not exists。干得好。 好的,我更改了一个代码,并且输出与您完全相同,问题在于我试图从外部访问我的数据库,因为它仍然无法正常工作,那里一定有问题,-重新运行应用程序和测试数据持久化成功 - "sa; sa; null " 输出如预期。谢谢您的帮助。 @MadProgrammer 如果您有兴趣,请查看我自己对这个问题的回答,最后的问题根本不在我的代码中:D,我仍然感谢您的帮助,我已经将您的答案标记为正确的 +upvote bud 似乎问题出在 razorsql 的 jdbc url 中。【参考方案2】:

在进一步检查我的代码后:原始帖子中的代码可以正常工作,无需更改。

我面临的问题是我尝试从 RazorSQL 连接到我的数据库的一种方式,我使用的 JDBC URL 与我在我的代码中使用的确切 URL 不匹配,我省略了 ;DATABASE_TO_UPPER=false 在让我连接到它 db 的 Schema 没有改变。使用正确的 JDBC URL 后,我能够在 RazorSQL 中看到包含数据的表。

如果您遇到与我一样的问题,尝试使用您在代码中使用的 JDBC URL,之后也可以使用选项。

网址失败

jdbc:h2:file:C:\Users\tomas\.OpenChannel\oc_database\dboc

正确的网址

jdbc:h2:file:C:\Users\tomas\.OpenChannel\oc_database\dboc;DATABASE_TO_UPPER=false

我从没想过这会是个问题。 :D

【讨论】:

以上是关于未在 H2 数据库上执行的 Sql 查询的主要内容,如果未能解决你的问题,请参考以下文章

多个 SQL 查询未在 Cakephp 中执行

H2 内存数据库未在 weblogic 中显示控制台,但在 Tomcat 中显示

CrudRepository 无法在 h2 db 上执行任何查询

如何计算使用 Hibernate 对 H2 数据库进行的 SQL 查询的数量

用 H2 数据库理解 JdbcConnectionPool

Mysql SQL查询DATEDIFF在H2中失败,其中模式是MYSQL