Самый простой способ войти, кто что обновил в CF-ORM / Hibernate? - PullRequest
3 голосов
/ 19 февраля 2010

Одним из требований моего проекта является регистрация того, кто (какой персонал) что обновил (с какой версии до какой версии). Пользовательский интерфейс должен показать, кто обновил сущность X, в какое время и что обновляется.

Какой самый чистый способ реализовать это?

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

Ответы [ 3 ]

2 голосов
/ 19 февраля 2010

Я веду отдельную таблицу для каждой таблицы, которую я проверяю.Имя таблицы одно и то же, схема другая.Пример: dbo.Usr = Audit.Usr.Audit.Usr включает 2 новых поля: новый первичный ключ и поле даты / времени.

Затем я использую триггеры.Я не согласен с людьми, которые говорят, что использование триггеров загрязняет модель данных.Если правила требуют отслеживания изменений в базе данных, то размещение правил в базе данных кажется подходящим местом.Как говорит Пол Нильсен в Библии SQL Server: «Любые правила, которые не соблюдаются на уровне базы данных, не являются правилами, это всего лишь предложения.

Вот пример, где я проверяю изменения в таблице usr.Это совпадение, что мы отслеживаем UsrID, который изменил таблицу Usr, поэтому есть поле с именем Usr_UsrID.В любой другой таблице, кроме таблицы Usr, поле с именем Usr_UsrID будет иметь смысл.

IF  EXISTS (SELECT * FROM sys.schemas WHERE name = N'Audit')
DROP SCHEMA Audit
GO
CREATE SCHEMA Audit AUTHORIZATION dbo
GO
CREATE TABLE Audit.AuditType(
AuditTypeID Int Identity(1,1) Constraint AuditTypeID Primary Key,
AuditTypeName Varchar(128),
AuditTypeDesc Varchar(128),
AuditTypeSort Int default 0
)
GO
INSERT INTO Audit.AuditType(AuditTypeName,AuditTypeSort,AuditTypeDesc) VALUES('Insert',1,'Insert')
INSERT INTO Audit.AuditType(AuditTypeName,AuditTypeSort,AuditTypeDesc) VALUES('Change',2,'Old Value')
INSERT INTO Audit.AuditType(AuditTypeName,AuditTypeSort,AuditTypeDesc) VALUES('New Value',3,'New Value')
INSERT INTO Audit.AuditType(AuditTypeName,AuditTypeSort,AuditTypeDesc) VALUES('Delete',4,'Delete')
GO
IF  EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'dbo.AuditInsert_Usr'))
DROP TRIGGER dbo.AuditInsert_Usr
GO
CREATE Trigger AuditInsert_Usr ON dbo.Usr AFTER Insert
NOT FOR REPLICATION AS
INSERT INTO Audit.Usr(AuditUsr_AuditTypeID,
UsrID,UsrName,UsrPassword,Usr_UsrID)
SELECT 1,
UsrID,UsrName,UsrPassword,Usr_UsrID
FROM Inserted
GO

IF  EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'dbo.AuditUpdate_Usr'))
DROP TRIGGER dbo.AuditUpdate_Usr
GO
CREATE Trigger AuditUpdate_Usr ON dbo.Usr AFTER Update
NOT FOR REPLICATION AS
INSERT INTO Audit.Usr(AuditUsr_AuditTypeID,
UsrID,UsrName,UsrPassword,Usr_UsrID)
SELECT 2,
Deleted.UsrID,Deleted.UsrName,Deleted.UsrPassword,Deleted.Usr_UsrID
FROM Inserted
JOIN Deleted
ON Inserted.UsrID = Deleted.UsrID
WHERE Inserted.UsrName  <> Deleted.UsrName
OR Inserted.UsrPassword <> Deleted.UsrPassword
OR Inserted.Usr_UsrID   <> Deleted.Usr_UsrID;
INSERT INTO Audit.Usr(AuditUsr_AuditTypeID,
UsrID,UsrName,UsrPassword,Usr_UsrID)
SELECT 3,
Inserted.UsrID,Inserted.UsrName,Inserted.UsrPassword,Inserted.Usr_UsrID
FROM Inserted
JOIN Deleted
ON Inserted.UsrID = Deleted.UsrID
WHERE Inserted.UsrName  <> Deleted.UsrName
OR Inserted.UsrPassword <> Deleted.UsrPassword
OR Inserted.Usr_UsrID   <> Deleted.Usr_UsrID;
GO

IF  EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'dbo.AuditDelete_Usr'))
DROP TRIGGER dbo.AuditDelete_Usr
GO
CREATE Trigger AuditDelete_Usr ON dbo.Usr AFTER Delete
NOT FOR REPLICATION AS
INSERT INTO Audit.Usr(AuditUsr_AuditTypeID,
UsrID,UsrName,UsrPassword,Usr_UsrID)
SELECT 4,
UsrID,UsrName,UsrPassword,Usr_UsrID
FROM Deleted
GO
1 голос
/ 19 февраля 2010

Иметь отдельную таблицу истории, которая отслеживает:

  1. таблица
  2. столбец
  3. операция (вставка, обновление, удаление)
  4. измененный ряд
  5. старое значение (для обновления)
  6. новое значение (для обновления)
  7. имя пользователя, который внес изменение
  8. отметка времени

Обновите его с помощью триггеров, и вам не нужно ни о чем беспокоиться.

Или исследуйте тему под названием "Изменение сбора данных" .Некоторые поставщики баз данных, такие как Oracle, встроили его в свой продукт.Вы просто должны включить его.Может быть, у вас уже есть.

0 голосов
/ 15 марта 2010

Мы можем отслеживать изменения с помощью триггеров, используя методы, описанные @cf_PhillipSenn и @duffymo в их ответах.

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

Триггеры могут затем получить идентификатор пользователя из идентификатора сеанса.

В Hibernate мы можем гарантировать, что этот процесс вызывается для каждого нового соединения, предоставив наш собственный org.hibernate.connection.ConnectionProvider, который вызывает процесс после открытия соединения.Этот класс, скорее всего, является подклассом DatasourceConnectionProvider.java или DriverManagerConnectionProvider.

CF-ORM может сделать это через свойство ormconfig .

Для SQL Server таблица пользователя и хранимой процедуры будет выглядеть так:

CREATE TABLE UserToSPID (
    SPID    int PRIMARY KEY,
    UserId  int
)

CREATE PROCEDURE dbo.[UserToSPID_Register]
    @UserId         int
AS
    delete from UserToSPID where spid=@@spid;
    insert into UserToSPID (SPID,userid) values (@@spid,@userid);
GO
...