【问题标题】:JDBC with H2 and MySQL mode: create procedure fails具有 H2 和 MySQL 模式的 JDBC:创建过程失败
【发布时间】:2022-01-25 11:58:18
【问题描述】:

代码说明

数据库连接

我尝试将 Java 对象存储在本地数据库而不使用外部数据库。 为此,我通过 Hibernate 将 JDBC 与 H2 一起使用:

    /**
     * @param connection the connection to set
     */
    public static void setConnectionHibernate() {
        Properties connectionProps = new Properties();
        connectionProps.put("user", "sa");
        try {
            Class.forName("org.h2.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        url = "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MODE=MySQL;";
    }

查询

我使用此代码将 PROCEDURE 存储在字符串中:

    static final String CREATE_PROCEDURE_INITPSEUDOS = "CREATE OR REPLACE PROCEDURE init_pseudos (MaxPseudo INT) BEGIN WHILE MaxPseudo >= 0 DO"
            +
            " INSERT INTO Pseudos (indexPseudo)" +
            " VALUES (MaxPseudo);" +
            " SET MaxPseudo = MaxPseudo - 1;" +
            " END WHILE;" +
            " END init_pseudos;";

查询执行

我用这段代码执行语句:

    public static void initBaseDonneePseudos() {
        try (Connection connection = DriverManager.getConnection(url, connectionProps);
                Statement stmt = connection.createStatement()) {
            stmt.execute(RequetesSQL.CREATE_TABLE_PSEUDOS);
            stmt.execute(RequetesSQL.CREATE_PROCEDURE_INITPSEUDOS);
            stmt.execute(RequetesSQL.CREATE_FUNCTION_RECUPEREPSEUDO);
            stmt.execute(RequetesSQL.INIT_TABLE_PSEUDOS);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

问题

测试

我执行这个测试来测试语句:

    @Nested
    class BaseDonneeInteractionTest {

        @BeforeEach
        public void setUp() {
            BaseDonnee.setConnectionHibernate();
        }

        @Test
        void testInitBaseDonnee() {
            assertDoesNotThrow(() -> BaseDonnee.initBaseDonneePseudos());
        }

    }

错误

但是我得到这个错误

我没有找到查询的问题,有人有解决这个问题的方法吗?

【问题讨论】:

  • 您应该将错误消息作为文本而不是图像发布。

标签: java stored-procedures jdbc h2


【解决方案1】:

问题是在 H2 中没有您尝试定义的显式过程或函数。

为此,H2 允许您创建使用过的定义函数。请考虑 reed 为适当的documentation

基本上,您通过为一堆 Java 代码声明 ALIAS 来创建用户定义的函数。

例如,在您的用例中,您的 CREATE_PROCEDURE_INITPSEUDOS 可能类似于:

CREATE ALIAS INIT_PSEUDOS AS  $$
import java.sql.Connection;
import java.sql.Statement;
import java.sql.SQLException;
@CODE
void init_pseudos(final Connection conn, final int maxPseudo) throws SQLException {
  try (Statement stmt = conn.createStatement()) {
    while (maxPseudo >= 0) do {
      stmt.execute("INSERT INTO Pseudos (indexPseudo)  VALUES (MaxPseudo);");
      maxPseudo = maxPseudo - 1;
    }
  }
}
$$;

注意以下几点:

  • 正如我所说,您将用户定义的函数定义为 Java 代码。该 Java 代码应包含在两个 $$ 分隔符之间。
  • 虽然我明确包含了一些导入,但您可以在代码中使用 java.utiljava.sql 包中的任何类。如果你想明确地包含一些导入,或者如果你需要来自其他包的类而不是提到的,则应在第一个 $$ 标记之后提供相应的导入。此外,您需要包含 @CODE 信号 H2,您的导入结束和实际 Java 方法开始的位置。
  • 如果您需要在代码中引用 Connection 到数据库,它应该是您方法的第一个参数。
  • 倾向于引发而不是隐藏异常:它将允许您的事务作为一个整体适当地提交或回滚。

你可以像往常一样调用这样的函数:

CALL INIT_PSEUDOS (5);

请为maxPseudo 参数提供适当的值。

请将所提供的代码视为使用示例:您可以通过不同方式改进代码,例如使用PreparedStatements 代替Statements 以提高效率、检查参数的可空性等。

【讨论】:

    【解决方案2】:

    “MySQL 兼容模式”不会使 H2 与 MySQL 100% 兼容。它只是改变了一些事情。 documentation 列出了它们:

    • 允许使用 INDEX(..) 或 KEY(..) 在 CREATE TABLE 语句中创建索引。示例:create table test(id int primary key, name varchar(255), key idx_name(name));
    • 将浮点数转换为整数时,小数位不会被截断,但值会四舍五入。
    • INSERT 语句支持 ON DUPLICATE KEY UPDATE,由于此功能 VALUES 在某些上下文中具有特殊的非标准含义。
    • 部分支持 INSERT IGNORE,如果未指定 ON DUPLICATE KEY UPDATE,可用于跳过具有重复键的行。
    • 部分支持 REPLACE INTO。
    • 从 CHAR 值的右侧开始修剪空格。
    • REGEXP_REPLACE() 使用 \ 进行反向引用。
    • 日期时间值函数在命令中返回相同的值。
    • 0x 文字被解析为二进制字符串文字。
    • DISTINCT 查询的 ORDER BY 子句中允许使用不相关的表达式。
    • 部分支持某些特定于 MySQL 的 ALTER TABLE 命令。
    • TRUNCATE TABLE 重新启动生成列的下一个值。
    • 如果手动指定了标识列的值,则会更新其序列以在插入后生成值。
    • NULL 值的作用类似于 DEFAULT 值是对标识列的分配。
    • 引用约束不需要现有的主键或引用列上的唯一约束,如果此类约束不存在,则会自动创建唯一约束。
    • 支持 LIMIT / OFFSET 子句。
    • 可以使用AUTO_INCREMENT 子句。
    • YEAR 数据类型被视为 SMALLINT 数据类型。
    • GROUP BY 子句可以包含 SELECT 列表中从 1 开始的表达式位置。
    • 允许在数值和布尔值之间进行不安全的比较运算符。

    就是这样。没有什么关于程序的。正如@jccampanero 在另一个答案中指出的那样,如果要创建存储过程,则必须使用特定于 H2 的语法。

    【讨论】:

      猜你喜欢
      • 2021-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-14
      相关资源
      最近更新 更多