2015-06-30 2 views
1

Мне нужно добавить soft delete Функция для всех объектов, которыми управляет мое приложение. Для того, чтобы выполнить, что я создал базовый класс сущностей (MappedSuperclass) с удалено поля, как показано ниже:Правильное использование псевдонимов таблицы в Hibernate Interceptor

@MappedSuperclass 
public abstract class BaseVersionableEntity { 

    @Id 
    @Basic(optional = false) 
    @NotNull 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "ID", nullable = false) 
    protected Long id; 

    @Version 
    @Column(name = "VERSION", nullable = false) 
    protected Long version; 

    @Basic 
    @Column(name = "DELETED") 
    protected boolean deleted; 

    public boolean isDeleted() { 
     return deleted; 
    } 

    public void setDeleted(boolean deleted) { 
     this.deleted = deleted; 
    } 

    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    public Long getVersion() { 
     return version; 
    } 

    public void setVersion(Long version) { 
     this.version = version; 
    } 

    // equals/hashCode 

} 

С помощью перехватчика механизма Hibernate, я настроил мягкого удаление перехватчика, чтобы поймать все запросы что спящий режим выполняет:

public class SoftSelectInterceptor extends EmptyInterceptor{ 

    private static final long serialVersionUID = 1L; 

    @Override 
    public String onPrepareStatement(String sql) { 

     if(sql.startsWith("select")){ 
      sql = sql.replace("where ","where deleted=0 and "); 
     } 

     return super.onPrepareStatement(sql); 
    } 
} 

Я добавил ниже перехватчик конфигурации для persistence.xml файла

<property name="hibernate.ejb.interceptor" value="com.my.organization.SoftSelectInterceptor"/> 

Обратите внимание, что есть SoftDeleteInterceptor, а также. Работает одинаково.

Когда я выполняю этот код Hibernate уловы выберите вызовы заявления в onPeraparedStatement метода, но он добавляет псевдоним таблицы перед полой таблицей. То есть, если имя таблицы reportTemplate, hibernate дать эту таблицу reportTemplate0 псевдоним. Поэтому мой оператор замены должен быть следующим:

sql = sql.replace("where ","where reportTemplate0.deleted=0 and "); 

Я могу разобрать строку sql и попытаться вывести правильные псевдонимы таблиц. Однако в сложных sql-операциях (когда один и тот же объект использовался несколько раз) было бы трудно сделать вывод.

Интересно, есть ли лучший способ сделать это.

ответ

1

Я вижу три варианта:

  1. Используйте Hibernate Filters. Главный недостаток: вы должны прикрепить фильтр для каждого объекта.

    @Entity 
    // The FilterDef can be declared at package level as well: 
    @FilterDef(name="alive", defaultCondition="deleted = 0") 
    // Turn on the filter for our entity: 
    @Filter(name="alive") 
    public class MyEntity { ... } 
    
  2. Используйте SQL-анализатор (есть достаточно там), изменить анализируемый результат и воссоздать SQL. Главный недостаток: для изменения достаточно достаточно тривиальных утверждений (включая подзапросы). Вы должны обязательно добавить ограничение только к затронутым таблицам.

  3. Используйте сервисную архитектуру с базовым сервисом, где вы всегда используете те же методы для загрузки/поиска объектов, которые строят правильный запрос. Главный недостаток: вы не можете использовать именованные запросы.
+0

вариант 1 и 3 не применяются в нашем случае, так как я должен дать общее решение с минимальным эффектом. Я рассматриваю вариант 2. Существует ли какой-либо глобальный параметр конфигурации для указания структуры табличных псевдонимов. Например, использовать префикс t (например, t1, t2) или использовать префикс имени класса сущностей alwayse и т. Д.? –

+0

Для псевдонимов нет конкретных параметров конфигурации. Обычно это _Entity Name_ + _a counter_ + '_' (см.' Org.hibernate.hql.ast.util.AliasGenerator.createName (String) '), но я не могу гарантировать это для всех сгенерированных SQL. В документации говорится, что _Subclasses of Loader do * not * должны использовать псевдонимы этой формы_ –

+0

. Я принял ваш ответ, так как опция 1 всегда применима, если мы не принимаем во внимание усилия. последний вопрос: Hibernate поддерживает аннотацию фильтра в MappedSupperClasses (начиная с версии 3.5.0). что, если бы я использовал только один фильтр в сопоставленном суперклассе и применял все сущности в проекте, наследует этот суперкласс. Есть ли недостатки такого подхода? –

0

Вы можете отобразить удаляемые объекты в представления базы данных, которые выбирают из исходных таблиц с условием фильтра (deleted = 0).

EDIT

К сожалению, это невозможно сделать это так, как вы пытаетесь.

1) Невозможно точно предсказать, как будут выглядеть псевдонимы, особенно со сложными запросами с несколькими объединениями и подзапросами. Даже если вы анализируете исходный код, он не является частью публичного API и как таковой может быть изменен.

Однако, если вы решите предпринять эту попытку (проанализируйте источник Hibernate для разбора запроса и генерации SQL), имейте в виду, что вы, вероятно, потратите свое лето всего лишь на то, что это сложная и огромная база кода и несколько очень важных запросов функций (например, left joins for non-associated entities) ждут годы для его рефакторинга.

2) Запросы (и подзапросы) без оговорки where не исключит удаленные строки (так как ваша замена не найдет матчей):

select c from MyEntity; 

3) Реже для где сочетание букв, но все еще возможно, , где может быть частью идентификатора или текстовой константы, и ваша замена сделает запрос недействительным. Предположим, кто-то добавляет два поля в объект Trip: fromWhere и toWhere. Возможно, это не хороший пример именования, но вы понимаете.

Вы могли бы решить эту проблему путем замены только вхождения всего where слова, но представьте запрос как:

select ... from ... where aColumn = 'A constant with the where word in it' 
+0

Я тоже подумал об этом ответе, но проигнорировал его, поскольку он зависит от базы данных, если сущность может быть изменена через представление. И я не могу использовать генерацию схемы для этих представлений и (что более важно) для таблиц, по крайней мере, мне понадобится дополнительное преобразование. –

+0

Насколько я понимаю, нет решения без боли. Спасибо за редактирование @Dragan –

Смежные вопросы