2010-02-19 66 views
3

我的項目的一個要求是記錄誰(哪個員工)更新了什麼(從什麼版本到哪個版本)。用戶界面需要在什麼時間顯示誰更新了實體X以及哪些內容已更新。最簡潔的方法來記錄誰更新了CF-ORM/Hibernate中的內容?

什麼是最簡潔的方式來實現呢?

出於討論目的,想象一下...帳戶有聯繫人,我需要存儲誰更新了聯繫人,何時更新了內容。

回答

2

我爲每個正在審覈的表保留一張單獨的表格。表名是相同的,架構是不同的。例如:dbo.Usr = Audit.Usr。 Audit.Usr包括2個新字段:新的主鍵和日期/時間字段。

然後我使用觸發器。我不同意那些認爲使用觸發器會污染數據模型的人。如果規則要求跟蹤數據庫的更改,那麼將規則放入數據庫似乎是合適的地方。正如Paul Nielsen在SQL Server的聖經中所說的:任何在數據庫級不執行的規則都不是規則,它們僅僅是建議。

以下是我正在審覈對usr表進行更改的示例。我們正在跟蹤更改了Usr表的UsrID,這是一個巧合,所以這就是爲什麼有一個名爲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 
+0

thx,但數據庫觸發器不適用於我,因爲它無法記錄誰對數據進行了更改。 – Henry 2010-02-19 19:10:29

1

有跟蹤一個單獨的歷史表:

  1. 操作(插入,更新,刪除)
  2. PK修改行
  3. 舊值(對更新)
  4. 新值(更新)
  5. 瘋狂者的用戶名E中的變化
  6. 時間戳

與觸發更新它,你不必擔心什麼。

或研究題爲"change data capture"的主題。一些數據庫供應商,如Oracle,已將其內置到他們的產品中。你只需打開它。也許你已經擁有了它。

+0

如何可以觸發跟蹤「是誰作出改變人的用戶名」的? – Henry 2010-02-19 19:11:01

+0

它必須以某種方式獲取用戶名。它將不得不被傳入。 – duffymo 2010-02-19 20:32:18

0

我們可以跟蹤通過使用他們的答案被 @cf_PhillipSenn描述的方法和@duffymo觸發器的變化。

這讓我們知道哪些用戶進行了每次更改。只要應用程序打開數據庫連接以將應用程序用戶標識映射到數據庫會話標識,我們就需要調用存儲過程。

觸發器可以從會話ID獲取用戶標識。

在Hibernate中,我們可以通過提供我們自己的org.hibernate.connection.ConnectionProvider來確保每個新連接都調用這個過程,它在打開連接後調用proc。這個類最有可能是DatasourceConnectionProvider.javaDriverManagerConnectionProvider的子類。

CF-ORM可以通過ormconfigproperty來做到這一點。

對於SQL Server,用戶會話表和存儲過程會是什麼樣子:

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

CREATE PROCEDURE dbo.[UserToSPID_Register] 
    @UserId   int 
AS 
    delete from UserToSPID where [email protected]@spid; 
    insert into UserToSPID (SPID,userid) values (@@spid,@userid); 
GO 
相關問題