Использование hibernate/hql для усечения таблицы?

Каков рекомендуемый способ усечения таблицы с помощью hibernate/hql?

Я пробовал это:

 Query query = session.createQuery("truncate table MyTable");
 query.executeUpdate();

Но это не сработало (усечение, похоже, нигде не задокументировано в hql...)


person user149100    schedule 11.08.2009    source источник
comment
Truncate не является стандартной командой DML или DDL, поэтому нормально, что она не поддерживается.   -  person Lluis Martinez    schedule 08.12.2009


Ответы (6)


Я предполагаю, что ужасным способом сделать это было бы удаление всего.

public int hqlTruncate(String myTable){
    String hql = String.format("delete from %s",myTable);
    Query query = session.createQuery(hql);
    return query.executeUpdate();
}
person Tom    schedule 11.08.2009
comment
В итоге я использовал это, так как обычно у меня есть только двадцать или около того записей, которые нужно удалить за раз... Спасибо! - person user149100; 12.08.2009
comment
@stunaz Конечно, truncat!=delete, но здесь есть компромиссное решение. - person Stephan; 06.12.2011

Вместо этого вы можете использовать session.createSQLQuery():

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

Излишне говорить, что это не идеально с точки зрения портативности. Вероятно, было бы неплохо определить этот запрос в сопоставлении и получить его в коде как именованный запрос.

person ChssPly76    schedule 11.08.2009
comment
Примечание createNativeQuery предпочтительнее после версии 5.2. - person aristotll; 08.09.2017

Будьте осторожны, усечение и удаление - это совершенно разные операторы sql:

  • delete – это DML, а truncate – DDL, что означает, что удаление можно откатить, а усечение нельзя откатить.
  • delete должен найти каждую строку одну за другой. усечение происходит мгновенно
  • для удаления используются журналы отмены, а для усечения нет

Если собрать все вместе:

  1. если вы хотите, чтобы его можно было откатить, вы не хотите использовать усечение
  2. if you use delete, given the size of the table you want to empty :
    • if the table is small you will see no difference
    • если таблица среднего размера, у вас будет плохая производительность
    • если таблица большая, у вас закончится место в табличном пространстве отмены, и вы не сможете ничего очистить

поэтому будьте осторожны с тем, какое утверждение вы действительно хотите использовать.

Что касается усечения таблицы с помощью hql, следует запретить запуск DDL (усечение, создание таблицы, удаление таблицы и т. д.) из приложения. Вы должны использовать удаление. Но если таблица большая, это тоже не сработает. Вот почему очистка таблицы в приложении — вообще плохая идея. Если вы хотите сделать некоторую очистку, часто лучше запускать truncate внутри скрипта sql один раз каждую ночь.

Обратите внимание, что я не знаю специфики вашего приложения и что оно говорит только в общих чертах.

person jeleb    schedule 28.05.2010

Я использовал синтаксис удаления в 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;
}

Отлично работает и полностью обрезает целевую таблицу. Используйте с осторожностью, так как ваш сервер БД будет выполнять эту инструкцию с большой эффективностью... :)

person Piko    schedule 14.02.2010

Для предотвращения SQL-инъекций вы можете использовать:

String escapedSQL = StringEscapeUtils.escapeSql(unescapedSQL);

из Apache Commons-Lang

метод StringEscapeUtils.escapeSql

person Andrzej Sydor    schedule 05.08.2019

Вы можете сделать это следующим образом:

    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());
            }
        });
    }
person mmdemirbas    schedule 04.09.2020