【问题标题】:Execute DDL from hibernate从休眠状态执行 DDL
【发布时间】:2010-07-10 21:09:36
【问题描述】:

我知道 SchemaExport 应该是我的朋友。但我正在使用 liquibase 并希望执行从 liquibase 生成的 DDL(纯 sql 语句),以便在每个测试方法之前重新创建数据库。

您是否发现以下代码存在问题?我想知道这似乎如此复杂......

public static int executeScript(String sqlFileOnClasspath) {
    Session sess = getSessionFactory().openSession();
    Transaction ta = sess.beginTransaction();
    int sqlCmd = 0;

    try {
        BufferedReader bReader = new BufferedReader(new InputStreamReader(
                  Util.class.getResourceAsStream(sqlFileOnClasspath), "UTF-8"));
        String line;
        while ((line = bReader.readLine()) != null) {
            if (line.startsWith("--") || line.trim().isEmpty())
                continue;

            final String tmp = line;
            sess.doWork(new Work() {

                @Override
                public void execute(Connection connection) throws SQLException {
                    connection.createStatement().execute(tmp);
                }
            });
            sqlCmd++;
        }
    } catch (Exception ex) {
        log.error("Couldn't execute " + sqlFileOnClasspath, ex);
    } finally {
        ta.commit();
        sess.close();
    }

    return sqlCmd;
}

顺便说一句:对于 liquibase,您需要这样做:

    // remove all hibernate managed tables
    SchemaExport schemaTool = new SchemaExport(getConfiguration()); 
    schemaTool.drop(false, true);

    // DROP TABLE DATABASECHANGELOGLOCK;
    // DROP TABLE DATABASECHANGELOG;
    executeScript("/drop-none-hib.sql");

    // now execute the DDL statements from liquibase
    int sqlCmd = executeScript("/schema.sql");
    log.info("Executed " + sqlCmd + " sql commands");

【问题讨论】:

    标签: sql hibernate ddl


    【解决方案1】:

    安全

    直接执行未准备好的语句可能会导致 SQL 注入。但是,您似乎是从静态文件中读取 DDL 语句,所以这应该不是问题,只是想注意这一点。

    异常处理

    完全缺失,例如正确关闭输入流、连接等。此外,如果抛出任何SQLExceptions,它会丢失有关哪些语句失败的详细信息。 sqlCmd 变量也会计算失败的语句,所以我怀疑这个计数器的用处。

    解析 SQL/DDL

    您正在测试-- 样式的 cmets,但不是/* */ cmets。总有一天会咬你的。此外,解析器假定每行有一条 SQL 语句。较长的语句可能是多行的,并以需要修剪的分号结尾。虽然不确定 liquibase 是如何生成语句的,所以这可能不是一个真正的问题。

    事务处理

    DDL 语句无论如何都无法回滚,因此不确定事务是否有用。如果我错了,请纠正我。

    否则,因为它是用于测试,我看起来也很好。

    【讨论】:

    • 酷,非常感谢!对于 TA 处理:我希望你知道 ;-)
    • 当一个DDL执行成功时,会隐式执行一个COMMIT,所以不能手动回滚。但是,如果 DDL 出错,它会自动回滚(例如,DROP TABLE 要么执行成功,表永远消失,要么在表存在且处于一致状态时无法工作)searchoracle.techtarget.com/answer/…
    • 仅供参考,DDL 可以在某些数据库中回滚(至少 Postgresql 和 MS)。
    【解决方案2】:

    您为什么不简单地使用hbm2ddl.auto 配置?

    或者使用事务测试在每次测试后将数据库回滚到其原始状态?

    【讨论】:

    • 我认为在后台使用 SchemaExport => 正如我所说:liquibase create + 为我管理 DDL。
    • 是的,我考虑过“事务性测试”,但我经常在我的测试中提交一些东西,例如测试是否会抛出一些异常(唯一约束或乐观锁定等)
    猜你喜欢
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    • 2011-07-20
    • 1970-01-01
    • 2012-12-30
    • 2015-08-30
    • 1970-01-01
    相关资源
    最近更新 更多