2010-05-07 7 views
4

В настоящее время я работаю с Hibernate Envers.Как удалить записи из моей таблицы аудита?

Как удалить записи в таблице аудита, связанные с объектом, который я хочу удалить? Моя сущность не имеет отношения к другим объектам.

я понял, что я должен сделать это в onPostDelete методе моего пользовательского слушателя:

import org.hibernate.envers.event.AuditEventListener; 
import org.hibernate.event.PostCollectionRecreateEvent; 
import org.hibernate.event.PostDeleteEvent; 
import org.hibernate.event.PostInsertEvent; 
import org.hibernate.event.PostUpdateEvent; 
import org.hibernate.event.PreCollectionRemoveEvent; 
import org.hibernate.event.PreCollectionUpdateEvent; 

public class MyListener extends AuditEventListener { 

    ... 
    @Override 
    public void onPostDelete(PostDeleteEvent arg0) { 
    // TODO Auto-generated method stub 
    super.onPostDelete(arg0); 
    } 
    ... 

} 

Я прочитал документацию, форумы, много вещей, но я не могу понять это. Может быть, это невозможно, я не знаю.

Кто-нибудь когда-либо делал это раньше?

ответ

1

Хорошо, что я сделан на 50% для тех, кто хочет знать.

Благодаря создателю Hibernate Envers, Адам Барского, цитирую:

«Идентификатор» является зимуют ключевое слово для идентификатора хозяйствующего субъекта, независимо от имен; в случае аудиторских объектов, идентификатор составной и называется «originalId». Try:

"delete from full.package.name.User_AUD u where u.originalId.id = :userid" 

Но теперь, я также хотел бы, чтобы удалить записи, относящиеся к ревизии таблицы в моей revinfo таблице.

Если у кого-то есть ключ, дайте мне знать.

0

Элементы аудита обычно добавляются, а не удаляются, даже если связанный объект удален, поэтому я не думаю,, что API-интерфейс Envers обеспечивает поддержку этого.

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

+0

Спасибо Паскаль за ваше время. Как вы сказали, похоже, что API Envers не поддерживает эту поддержку. После просмотра нескольких форумов я нашел ключ. мне придется написать запрос HQL: «удалить из full.package.name.User_AUD ˙U где u.id =: Идентификатор_пользователь» Это половина работает, потому что сейчас я застрял с проблемой Hibernate ... –

+0

Вам просто нужно использовать частный аксессуар, чтобы изменить выбор для удаления, я просто опубликую рабочее решение без родного SQL –

1

Это полностью работает для меня, и не родного запроса не требуются

AuditQuery aq = auditReader.createQuery() 
        .forRevisionsOfEntity(ErpEmploye.class, true, false);  
aq.add(AuditEntity.id().eq(employe.getCodeId())); 
aq.add(AuditEntity.relatedId("period").eq(erpPeriod.getCodeId())); 
List result = aq.getResultList();//parameters must be added, this call is required 
if (result.size()>0){ 
    Query query = (Query) PrivateAccessor.invokePrivateMethod(aq, "buildQuery", new Object[0]); 
    String queryString = (String) PrivateAccessor.getPrivateField(query, "queryString", true); 
    PrivateAccessor.setPrivateField(query, "queryString", queryString.replace("select e__ from", "delete from"), true); 
    getDAO().executeQuery(query);//transaction required    
} 
1

Если вы хотите, чтобы уничтожить пересмотр по идентификатору, вы можете получить доступ к таблице Envers непосредственно с помощью родной запроса. Есть две таблицы, содержащие ссылки на ревизию. Предполагая, что ваша таблица аудита использует обычный суффикс _AUD, вы можете найти имя таблицы сущностей программным путем.

Вот некоторые фрагменты написаны на Котлин:

fun getAuditTableName(em: EntityManager, aClass: Class<*>): String { 
    return getAuditTableName(em, aClass.name) + "_AUD" 
} 

fun getEntityTableName(em: EntityManager, aClass: Class<*>): String { 
    val session = em.unwrap(Session::class.java) as Session 
    val sessionFactory = session.sessionFactory 
    val hibernateMetadata = sessionFactory.getClassMetadata(className) 
    val persister = hibernateMetadata as AbstractEntityPersister 
    return persister.tableName 
} 

Теперь, когда у нас есть имя таблицы, мы можем удалить строки в таблицах. (Поместите это в блок транзакций JPA, замените контент по мере необходимости и настройте SQL для своего провайдера). Поэтому, учитывая MyEntityClass и myRevisionId, мы можем сделать что-то вроде этого:

val em:EntityManager = getEntityManager() 
    val auditTableName = getAuditTableName(MyEntityClass::class.java) 

    em.createNativeQuery("delete from `$auditTableName` where REV=${myRevisionId}").executeUpdate() 
    em.createNativeQuery("delete from REVINFO where REV=${myRevisionId}").executeUpdate() 

Если вы хотите удалить с помощью параметра другой, чем RevisionId, просто запрос для тех revisionIds в таблице entity_AUD, а затем удалите найденные строки таким образом.

Имейте в виду, что versionId может быть связан с более чем 1 сущностью, и все записи будут удалены в предыдущем методе. Чтобы удалить ревизию для одного объекта, вам понадобятся идентификаторы имени и сущности имени объекта.

Вот код для динамического получения имени поля:

fun getEntityKeyNames(em: EntityManager, entityClass: Class<*>): List<String> { 
    val session = em.unwrap(Session::class.java) as Session 
    val sessionFactory = session.sessionFactory 
    val hibernateMetadata = sessionFactory.getClassMetadata(entityClass.name) 
    val persister = hibernateMetadata as AbstractEntityPersister 
    return persister.keyColumnNames.toList() 
} 
Смежные вопросы