除非使用Transaction,否则为什么删除表不能与SQLServer一起使用?

时间:2015-06-02 10:52:28

标签: java sql-server transactions

我正在运行一个可以与数据库通信的Spring Java Web Application。数据库的类型可由用户选择,可以是MySQL,Oracle或SQLServer。

我不明白为什么以下代码在使用SQLServer时无法删除表(它适用于Oracle和MySQL):

public void dropTables(String... tableNames) {
    Session session = localSessionFactory.getObject().openSession();
    try {
        dropTables(session, tableNames);
    } finally {
        session.close();
    }
}

private void dropTables(Session session, String... tableNames) {
    for(String currentTable : tableNames) {
        SQLQuery createSQLQuery = session.createSQLQuery("drop table "+currentTable);
        createSQLQuery.executeUpdate();
    }
}

该表未能删除。就好像Drop SQL Query没有运行一样。该表仍然存在并保留其内容。调用executeUpdate的返回值为0.

但是,如果我通过在drop语句周围添加一个Transaction来修改代码,那么SQLServer上的drop就会成功:

public void dropTables(String... tableNames) {
    Session session = localSessionFactory.getObject().openSession();
    Transaction tx = null;
    try {
        tx = session.beginTransaction();
        dropTables(session, tableNames);
    } finally {
        tx.commit();
        session.close();
    }
}

private void dropTables(Session session, String... tableNames) {
    for(String currentTable : tableNames) {
        SQLQuery createSQLQuery = session.createSQLQuery("drop table "+currentTable);
        createSQLQuery.executeUpdate();
    }
}

为什么我必须围绕它进行交易?我认为,由于DROP是一个DDL语句,因此事务不是必需的。有谁可以帮我解释一下?

2 个答案:

答案 0 :(得分:1)

与Oracle和MySQL不同,SQL Server支持事务性DDL。这意味着您必须提交DDL语句 - 除非您的连接配置为使用自动提交。

Transactional DDL是一个非常好的功能,因为它允许“全有或全无”的迁移脚本。回滚也将回滚drop table

事务性DDL对SQL Server来说并不特别。 Postgres,DB2和Firebird也支持这一点(仅举几例)。

答案 1 :(得分:0)

我猜Hibernate推迟了数据库调用。因为这与Hibernate无关,我可能会直接使用数据库(使用数据源)。