Оказывается, что на самом деле есть способ сделать это с помощью прослушивателей событий, не раскрывая соединяющиеся таблицы.Вам просто нужно, чтобы ваш прослушиватель событий реализовал IPostCollectionRecreateEventListener или IPreCollectionRecreateEventListener.На основании моего тестирования эти события запускаются для измененных коллекций всякий раз, когда сеанс сбрасывается.Вот мой код прослушивателя событий для метода PostRecreateCollection.
public void OnPostRecreateCollection(PostCollectionRecreateEvent @event)
{
var session = @event.Session.GetSession(EntityMode.Poco);
var propertyBeingUpdated = @event.Session.PersistenceContext.GetCollectionEntry(@event.Collection).CurrentPersister.CollectionMetadata.Role;
var newCollectionString = @event.Collection.ToString();
var oldCollection = (@event.Collection.StoredSnapshot as IList<object>).Select(o => o.ToString()).ToList();
var oldCollectionString = string.Join(", ",oldCollection.ToArray());
if (newCollectionString == oldCollectionString || (string.IsNullOrEmpty(newCollectionString) && string.IsNullOrEmpty(oldCollectionString)))
return;
User currentUser = GetLoggedInUser(session);
session.Save(new Audit
{
EntityName = @event.AffectedOwnerOrNull.GetType().Name,
EntityId = (int)@event.AffectedOwnerIdOrNull,
PropertyName = propertyBeingUpdated,
AuditType = "Collection Modified",
EventDate = DateTime.Now,
NewValue = newCollectionString,
OldValue = oldCollectionString,
AuditedBy = Environment.UserName,
User = currentUser
});
}
Самая сложная часть - получение имени обновляемой коллекции.Вы должны соединить свой путь через PersistenceContext, чтобы получить Persister для коллекции, которая дает вам доступ к ее метаданным.
Поскольку ни одно из этих событий или слушателей не задокументировано, я не знаю, было ли выброшено это событиев других ситуациях, кроме flush, существует вероятность, что он может создать ложные записи аудита.Я планирую провести дальнейшие исследования в этой области.