【问题标题】:Using hibernate/hql to truncate a table?使用 hibernate/hql 截断表?
【发布时间】:2010-11-18 18:18:15
【问题描述】:

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

我试过了:

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

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

【问题讨论】:

  • 截断不是标准的DML或DDL命令,所以不支持是正常的。

标签: hibernate hql truncate


【解决方案1】:

您可以改用session.createSQLQuery()

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

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

【讨论】:

  • 注意createNativeQuery是5.2以后的首选
【解决方案2】:

小心,truncate 和 delete 是完全独立的 sql 语句:

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

如果你把它们放在一起:

  1. 如果你希望它是可回滚的,你不想使用截断
  2. 如果你使用删除,给定你想清空的表的大小:
    • 如果表很小,您将看不出任何区别
    • 如果表是中等大小,则性能会很差
    • 如果表很大,您将用完 undo 表空间中的空间,并且您将无法清空任何内容

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

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

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

【讨论】:

    【解决方案3】:

    我想一种可怕的做法是删除所有内容。

    public int hqlTruncate(String myTable){
        String hql = String.format("delete from %s",myTable);
        Query query = session.createQuery(hql);
        return query.executeUpdate();
    }
    

    【讨论】:

    • 我最终使用了它,因为我通常一次只删除大约 20 条记录...谢谢!
    • @stunaz Sure truncat!=delete 但这里的解决方案是妥协
    【解决方案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;
    }
    

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

    【讨论】:

      【解决方案5】:

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

      String escapedSQL = StringEscapeUtils.escapeSql(unescapedSQL);

      来自Apache Commons-Lang

      方法StringEscapeUtils.escapeSql

      【讨论】:

        【解决方案6】:

        你可以这样做:

            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());
                    }
                });
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-08-16
          • 1970-01-01
          • 1970-01-01
          • 2011-02-23
          • 2014-01-29
          • 1970-01-01
          • 1970-01-01
          • 2015-05-21
          相关资源
          最近更新 更多