2008-11-11 3 views
3

Я пытаюсь проверить действие, которое пользователь выполнил, что привело к изменениям в соответствующих таблицах. Например, если пользователь был переводить деньги между счетами 2 это создаст следующую последовательность событий:Отображение схемы схемы с помощью Hibernate и AOP

  1. Вставить сумму перевода в таблицу передачи
  2. сумму перевода Вычесть из баланса в баланс Таблица для счета 1.
  3. Добавить сумму перевода баланса в таблице баланса для счета 2.

сообщение родительского аудита для всех таблиц будет: «Пользователь генерироваться перевод на сумму XXX»

Это достигается с помощью следующей схемы: schema

alt text http://img48.imageshack.us/img48/7460/auditloggingiv6.png

Вопрос в том, как я могу представить это в спящий режим?

Я создал следующее:

В Равновесие и файлы сопоставления переводополучателя

<set name="auditRecords" table="TransferAuditRecord" inverse="false" cascade="save-update"> 
    <key> 
    <column name="AuditRecordID" not-null="true" /> 
    </key> 
    <one-to-many class="audit.AuditRecord"/> 
</set> 

Передача и баланс классов затем реализовать IAuditable, который имеет методы

public void setAuditRecords(Set<AuditRecord> auditRecord); 
public Set<AuditRecord> getAuditRecords(); 

В файле отображения AuditRecord, я есть :

<many-to-one name="parentAuditRecord" lazy="false" 
      column="parent_id" 
      class="audit.AuditRecord" 
      cascade="all" /> 

Тогда в классе Logging с помощью АОП и гибернации Перехватчики у меня есть:

AuditRecord auditRecord = new AuditRecord(); 
auditRecord.setUser(userDAO.findById(
    org.springframework.security.context.SecurityContextHolder.getContext() 
     .getAuthentication().getName())); 

auditRecord.setParentAuditRecord(getCurrentActiveServiceRecord()); 

auditable.getAuditRecords().add(auditRecord); 

Тогда в классе обслуживания я называю следующий метод, заключенный в сделке:

save(balance1); 
save(balance2); 
transfer.setPassed(true); 
update(transfer); 

parentAuditRecord создается с помощью AOP с потоковым безопасным стеком, а AuditRecordType_id задается с помощью аннотаций метода.

Я оставил «пройденный» столбец на переносном столе. Раньше я вызываю save (transfer), чтобы вставить сумму перевода в таблицу Transfer с переданным значением false. (Это действие также проверяется).

Мои требования немного более сложным, чем вышеприведенный пример: P

Так последовательность событий для выше должно быть:

  1. Update Transfer Таблица
  2. Вставьте в AuditRecord (Parent)
  3. Вставить в AuditRecord (Ребенок)
  4. Вставить в TransferAuditRecord
  5. Вставки в балансе Таблицу
  6. Вставить в AuditRecord (ребенок)
  7. Вставить в BalanceAuditRecord
  8. Вставить в Balance таблицу
  9. Вставить в AuditRecord (ребенок)
  10. Вставить в BalanceAuditRecord

Однако параметры каскада, определенные выше, выходят из строя в операторе обновления. Hibernate отказывается вставлять запись в таблицу «многие ко многим» (даже если unsaved-value = «any» в Mapping AuditRecord). Я всегда хочу вставлять строки в таблицы «многие-ко-многим», поэтому потенциально одна Transfer имеет много записей аудита, обозначающих предыдущие события. Однако последнее событие определяет сообщение, которое пользователь хочет видеть. Hibernate либо пытается обновить таблицу «многие ко многим», либо предыдущие записи AuditRecord, либо просто отказывается вставлять в AuditRecord и TransferAuditRecord, бросая исключение TransientObjectException.

Аудиторский сообщение извлекается что-то вроде этого:

msg=... + ((AuditRecord) balance.getAuditRecords().toArray()[getAuditRecords().size()-1]) 
    .getParentAuditRecord().getAuditRecordType().getDescription() + ...; 

Сообщение должно сказать что-то вроде этого: "Имя пользователя установить передачу переданному в 12:00 11-окт-2008"

EDIT Я решил пойти с явным отображением таблицы «много-ко-многим» (с соответствующим интерфейсом), а затем в afterTransactionCompletion, вызвав сохранение записи родительского аудита (которая каскадирует сохранение в дочерние записи аудита), а затем явно сохраняет интерфейс по всем дочерним картам столы. Это не настоящая история аудита, а не неинвазивный метод записи действий пользователя. Я рассмотрю Envers, если мне понадобится более полная история аудита на более позднем этапе.

ответ

1

Похоже, что отношения между parentAuditRecord и Transferauditrecord и баланс auditrecord не должны быть едиными для многих. Когда я читаю, что вы набрали, я рассматриваю его как таблицу для каждого подкласса, использующего эту иерархию аудита, которая является взаимно-однозначным отношением.

http://www.hibernate.org/hib_docs/reference/en/html/inheritance.html

Вы также можете проверить проект Envers сервера JBoss.

0

На уровне дизайна кажется, что вставка только дизайна db будет работать здесь чудесами.

Если вы хотите, чтобы держать его так, как это прямо сейчас (который я уверен, что вы делаете), вы можете посмотреть в спящем режиме слушателей/перехватчик/события (четко определенные в документе: http://www.hibernate.org/hib_docs/v3/reference/en-US/html_single/)

Else , Я просто заглянул в JBoss Envers, и это тоже кажется очень полезным.

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