Hibernate @SQLDelete sql не добавляет схему

Я пытаюсь использовать аннотацию @SQLDelete Hibernate для мягкого удаления. Он хорошо работает, когда схема БД статична, т.е. Передает ее в SQL.
К сожалению, кажется, что SQL передан как EntityPersister (cf EntityClass method CustomSQL createCustomSQL(AnnotationInstance customSqlAnnotation), поэтому я не могу найти способ передать имя схемы динамически, как в исходных SQL-запросах, используя {h-schema}
Кто-нибудь нашел хорошее обходное решение для этой проблемы (я использую Hibernate 4.3.5)?

Изменить: если не существует реального решения, я в конечном итоге изменил исходный код кода org.hibernate.persister.entity.AbstractEntityPersister, заменив заполнитель схемы при настройке пользовательских SQL-запросов в методе doLateInit.

Edit2. Я создал проблему для этого поведения в Hibernate JIRA. Я создам запрос на перенос позже сегодня, и я хочу, чтобы команда Hibernate приняла его

Ответ 1

Используйте вот так

@SQLDelete(sql = "UPDATE {h-schema}LEAVE  SET STATUS = 'DELETED' WHERE id = ?", check = ResultCheckStyle.COUNT)

Ответ 2

Мягкие удаления с использованием аннотаций Hibernate.

Как указано автором ниже:

В настоящее время я работаю над приложением Seam, которое нуждается в мягких удалениях в базе данных. Справа вы можете увидеть фрагмент моей диаграммы базы данных, содержащий таблицу CUSTOMER и APP_USER. Это просто одностороннее отношение, но важно отметить, что это поле "DELETED" в каждой таблице. Это поле, которое будет использоваться для отслеживания мягкого удаления. Если поле содержит '1, запись была удалена, и если она содержит' 0, запись не была удалена.

введите описание изображения здесь

До ORM, таких как Hibernate, мне пришлось бы отслеживать и устанавливать этот флаг самостоятельно с помощью SQL. Было бы очень сложно сделать, но кто хочет написать кучу кода шаблона, чтобы отслеживать, была ли удалена запись. Здесь спящий режим и аннотации приходят на помощь.

Ниже приведены 2 класса Entity, которые были сгенерированы Hibernate, используя шов. Я пропустил части кода для ясности.

Customer.java

//Package name...

//Imports...

@Entity
@Table(name = "CUSTOMER")
//Override the default Hibernation delete and set the deleted flag rather than deleting the record from the db.
@SQLDelete(sql="UPDATE customer SET deleted = '1' WHERE id = ?")
//Filter added to retrieve only records that have not been soft deleted.
@Where(clause="deleted <> '1'")
public class Customer implements java.io.Serializable {
    private long id;
    private Billing billing;
    private String name;
    private String address;
    private String zipCode;
    private String city;
    private String state;
    private String notes;
    private char enabled;
    private char deleted;
    private Set appUsers = new HashSet(0);

    // Constructors...

    // Getters and Setters...

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "customer")
    // Filter added to retrieve only records that have not been soft deleted.
    @Where(clause = "deleted <> '1'")
    public Set getAppUsers() {
        return this.appUsers;
    }

    public void setAppUsers(Set appUsers) {
        this.appUsers = appUsers;
    }
}

AppUser.java

//Package name...

//Imports...

@Entity
@Table(name = "APP_USER")
//Override the default Hibernation delete and set the deleted flag rather than deleting the record from the db.
@SQLDelete(sql="UPDATE app_user SET deleted = '1' WHERE id = ?")
//Filter added to retrieve only records that have not been soft deleted.
@Where(clause="deleted <> '1'")
public class AppUser implements java.io.Serializable {
    private long id;
    private Customer customer;
    private AppRole appRole;
    private char enabled;
    private String username;
    private String appPassword;
    private Date expirationDate;
    private String firstName;
    private String lastName;
    private String email;
    private String phone;
    private String fax;
    private char deleted;
    private Set persons = new HashSet(0);

    // Constructors...

    // Getters and Setters...
}

Следующие два шага - все, что я должен был сделать для реализации мягкого удаления.

  • Добавлена ​​аннотация @SQLDelete, которая переопределяет значение по умолчанию Hibernate delete для этого объекта.
  • Добавлена ​​аннотация @Where для фильтрации запросов и возврата записи, которые были мягко удалены. Отметим также, что в Класс CUSTOMER добавил @Where в коллекцию appUsers. Это необходимо получить только приложения для этого клиента, у которых нет был мягко удален.

Viola! Теперь, когда вы удаляете эти объекты, он установит поле "DELETED" в поле "1" и при запросе этих объектов он будет возвращать только записи, содержащие "0 в " УДАЛИТЬ ".

Трудно поверить, но это все, что нужно для реализации мягких удалений с использованием аннотаций Hibernate.

Примечание:

также отметим, что вместо использования операторов @Where(clause="deleted ‘1’") вы можете использовать фильтр hibernate (http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-hibspec-filters), чтобы глобально отфильтровывать все удаленные объекты. Я обнаружил, что определение 2 менеджеров сущностей ("обычный, который фильтрует удаленные элементы, а другой, который не подходит для редких случаев...), обычно довольно удобен.

Использование EntityPersister

Вы можете создать DeleteEventListener, например:

public class SoftDeleteEventListener extends DefaultDeleteEventListener {

/**
 * 
 */
private static final long serialVersionUID = 1L;

@Override
public void onDelete(DeleteEvent event, Set arg1) throws HibernateException {
    Object o = event.getObject();
    if (o instanceof SoftDeletable) {
        ((SoftDeletable)o).setStatusId(1);
        EntityPersister persister = event.getSession().getEntityPersister( event.getEntityName(), o);
        EntityEntry entityEntry = event.getSession().getPersistenceContext().getEntry(o);
        cascadeBeforeDelete(event.getSession(), persister, o, entityEntry, arg1);

        cascadeAfterDelete(event.getSession(), persister, o, arg1);

    } else {
        super.onDelete(event, arg1);
    }
}
}

переместите его в свой persistence.xml, как этот

<property name = "hibernate.ejb.event.delete" value = "org.something.SoftDeleteEventListener"/> 

Кроме того, не забудьте обновить свои каскады в своих аннотациях.

Ссылка на ресурс: