20

使用 hibernate/hql 截断表的推荐方法是什么?

我试过这个:

查询查询 = session.createQuery("截断表 MyTable");
 查询.executeUpdate();

但它没有用(截断似乎没有记录在 hql 的任何地方......)

4

6 回答 6

43

您可以session.createSQLQuery()改用:

session.createSQLQuery("truncate table MyTable").executeUpdate();

不用说,这在便携性方面并不理想。在映射中定义此查询并在代码中将其检索为命名查询可能是一个好主意。

于 2009-08-11T20:36:48.237 回答
20

小心,截断和删除是完全独立的 sql 语句:

  • delete是DML,truncate是DDL,也就是说delete可以回滚,truncate不能回滚
  • delete 必须逐行查找。截断是瞬时的
  • delete 使用撤消日志,而 truncate 不使用

如果你把它们放在一起:

  1. 如果你希望它是可回滚的,你不想使用 truncate
  2. 如果你使用删除,给定你想要清空的表的大小:
    • 如果桌子很小,您将看不到任何区别
    • 如果桌子是中等大小,你会遇到糟糕的表现
    • 如果表很大,您将用完撤消表空间中的空间,并且您将无法清空任何内容

所以要小心你真正想要使用的语句。

至于如何用 hql 截断表,应该禁止从应用程序运行 DDL(截断、创建表、删除表等)。你应该使用删除。但是如果表很大,它也不会工作。这就是为什么在应用程序中清空表通常是个坏主意。如果您想做一些清理工作,通常最好每晚在 sql 脚本中运行一次 truncate。

请注意,我不知道您的应用程序的具体细节,它只是笼统地说。

于 2010-05-28T12:54:20.890 回答
16

我想一个可怕的方法是删除所有。

public int hqlTruncate(String myTable){
    String hql = String.format("delete from %s",myTable);
    Query query = session.createQuery(hql);
    return query.executeUpdate();
}
于 2009-08-11T20:31:13.787 回答
4

我在 HQL 中使用了删除语法来保持可移植性。效果很好:

public abstract class GenericDAOImpl<T, ID extends Serializable> implements GenericDAO<T, ID> {

private Class<T> persistentClass;

// Balance of dao methods snipped... :)

/**
 * Clears all records from the targetted file.
 * @throws DAOException
 */
public int truncate() throws DAOException {
    Session s = getSession();
    int rowsAffected = 0;
    try {
        Class c = getPersistentClass();
        String hql = "delete from " + c.getSimpleName();
        Query q = s.createQuery( hql );
        rowsAffected = q.executeUpdate();
    } catch ( HibernateException e ) {
        throw new DAOException( "Unable to truncate the targetted file.", e );
    }
    return rowsAffected;
}
/**
 * Returns a Class object that matches target Entity.
 *
 * @return Class object from constructor
 */
public Class<T> getPersistentClass() {
    return persistentClass;
}

效果很好,完全截断了目标表。请谨慎使用,因为您的数据库服务器将非常高效地执行此语句... :)

于 2010-02-14T10:11:14.940 回答
0

防止 SQL 注入,您可以使用:

String escapedSQL = StringEscapeUtils.escapeSql(unescapedSQL);

来自Apache Commons-Lang

方法StringEscapeUtils.escapeSql

于 2019-08-05T18:11:21.637 回答
0

你可以这样做:

    try (Session session = sessionFactory.openSession()) {
        session.doWork(connection -> {
            try (PreparedStatement preparedStatement = connection.prepareStatement("TRUNCATE TABLE " + tableName)) {
                preparedStatement.executeUpdate();
                System.out.printf("Truncated table: %s%n", tableName);
            } catch (SQLException e) {
                System.err.printf("Couldn't truncate table %s: %s: %s%n", tableName, e, e.getCause());
            }
        });
    }
于 2020-09-04T19:29:20.427 回答