我正在运行一个可以与数据库通信的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语句,因此事务不是必需的。有谁可以帮我解释一下?
答案 0 :(得分:1)
与Oracle和MySQL不同,SQL Server支持事务性DDL。这意味着您必须提交DDL语句 - 除非您的连接配置为使用自动提交。
Transactional DDL是一个非常好的功能,因为它允许“全有或全无”的迁移脚本。回滚也将回滚drop table
!
事务性DDL对SQL Server来说并不特别。 Postgres,DB2和Firebird也支持这一点(仅举几例)。
答案 1 :(得分:0)
我猜Hibernate推迟了数据库调用。因为这与Hibernate无关,我可能会直接使用数据库(使用数据源)。