Как регистрировать изменения записи? - PullRequest
0 голосов
/ 12 июня 2019

Я создаю приложение, в котором пользователи могут выполнять задания, которые должны быть одобрены другим пользователем. Таким образом, если утверждающий изменяет (обновляет) какие-либо данные, связанные с этой записью, мне необходимо сохранить эти изменения в таблице аудита, например https://github.com/spatie/laravel-activitylog.

Каков наилучший подход? Реализовать с помощью триггера или сравнить объекты? Есть ли у Android библиотека, которая может привести к этому?

Ниже приведена модель операции:

public class Operation {
    private int id;
    private String started_at;
    private int company_id;
    private int collaborator_id;
    private int approver_id;
    private int building_id;
    private String cost_center;
    private String ended_at;
    private int shift_id;
    private int service_id;
    private String invoice_number;
    private String transport_number;
    private String cod;
    private String lot;
    private int vehicle_id;
    private int carrier_id;
    private String vehicle_plate;
    private String cart_plate;
    private int amount;
    private int loose_cargo;
    private int palletized_load;
    private int gross_weight;
    private String comments;
    private int number_assistants;
    private int number_operators;
    private int number_tractors;
    private int number_samples;
    private int number_others;
}

Я пытался создать его, как показано ниже:

"CREATE TRIGGER " + OperationEntry.TRIGGER_NAME +
    " AFTER UPDATE " +
    " ON["+ OperationEntry.TABLE_NAME +"] " +
    " FOR EACH ROW " +
    " BEGIN " +
    " DECLARE changes VARCHAR(8000); " +
    " SET changes = '{'; " +
    " IF OLD. " + OperationEntry.COLUMN_ID + " <> " + " NEW. " + OperationEntry.COLUMN_ID + " THEN " +
    "SET changes = CONCAT(changes, );" +
    " END IF; " +
    " IF OLD. " + OperationEntry.COLUMN_COMPANY + " <> " + " NEW. " + OperationEntry.COLUMN_COMPANY + " THEN " +
    "SET changes = CONCAT(changes, );" +
    " END IF; " +
    " IF OLD. " + OperationEntry.COLUMN_BUILDING + " <> " + " NEW. " + OperationEntry.COLUMN_BUILDING + " THEN " +
    "SET changes = CONCAT(changes, );" +
    " END IF; " +
    " SET changes = CONCAT(changes, '}'); " +
    " END; ");

1 Ответ

3 голосов
/ 12 июня 2019

Использование ПОСЛЕ ОБНОВЛЕНИЯ Может показаться, что TRIGGER подходит и не требует дополнительного кода, кроме кода, необходимого для генерации TRIGGER.

Проблема в том, что существование TRIGGER не очевидно, но этот недостаток можно преодолеть с помощью подходящих комментариев в коде.

re: -

Я пытался создать его, как показано ниже:

"CREATE TRIGGER " + OperationEntry.TRIGGER_NAME +
    " AFTER UPDATE " +
    " ON["+ OperationEntry.TABLE_NAME +"] " +
    " FOR EACH ROW " +
    " BEGIN " +
    " DECLARE changes VARCHAR(8000); " +
    " SET changes = '{'; " +
    " IF OLD. " + OperationEntry.COLUMN_ID + " <> " + " NEW. " + OperationEntry.COLUMN_ID + " THEN " +
    "SET changes = CONCAT(changes, );" +
    " END IF; " +
    " IF OLD. " + OperationEntry.COLUMN_COMPANY + " <> " + " NEW. " + OperationEntry.COLUMN_COMPANY + " THEN " +
    "SET changes = CONCAT(changes, );" +
    " END IF; " +
    " IF OLD. " + OperationEntry.COLUMN_BUILDING + " <> " + " NEW. " + OperationEntry.COLUMN_BUILDING + " THEN " +
    "SET changes = CONCAT(changes, );" +
    " END IF; " +
    " SET changes = CONCAT(changes, '}'); " +
    " END; ");

Я не верю, что многое из вышеперечисленного сработает. В реализации SQLITE нет ключевого слова DECLARE, а ключевое слово IF очень ограничено.

Объединение значений также довольно странно.

Я бы посоветовал рассмотреть следующее на основании того, что вы пытаетесь сделать: -

-- Drop tables and triggers (allows rerunability for testing)
DROP TABLE IF EXISTS OperationEntry;
DROP TABLE IF EXISTS OperationEntryChanges;
DROP TRIGGER IF EXISTS OperationEntryTrigger;

-- Create the original/core table
CREATE TABLE IF NOT EXISTS OperationEntry (
    id INTEGER PRIMARY KEY, 
    company TEXT,   building TEXT
);
-- Create the logging table
CREATE TABLE IF NOT EXISTS OperationEntryChanges (
    oldid INTEGER, 
    newid INTEGER, 
    oldcompany TEXT, 
    newcompany TEXT, 
    oldbuilding TEXT, 
    newbuilding TEXT, 
    timestamp DEFAULT CURRENT_TIMESTAMP, -- assumes that you want some indications of when the update was made
    updatecounter DEFAULT 0 -- maybe over the top/not required may replace or compliment timestamp
    );
-- Create the logging trigger
CREATE TRIGGER OperationEntryTrigger
    AFTER UPDATE  ON OperationEntry
        BEGIN 
            INSERT INTO OperationEntryChanges 
                (oldid, newid, oldcompany, newcompany, oldbuilding, newbuilding, updatecounter) 
            VALUES
                (old.id, new.id, old.company, new.company, old.building, new.building, (SELECT count(*) + 1 FROM OperationEntryChanges)
                );
        END
;

-- Add some testing data
INSERT INTO OperationEntry (company, building) VALUES
        ('company1','Building1'),('company1','Building2'),('company1','Building3'),('company1','Building4'),
        ('company2','Building1'),('company2','Building2'),('company2','Building3'),
        ('company3','Building1'),('company3','Building2'),('company3','Building3'),('company3','Building4'),('company3','Building5')
;

-- Show the data prior to any updates
SELECT * FROM OperationEntry;
SELECT * FROM OperationEntryChanges;

-- Apply some updates
UPDATE OperationEntry SET company = company || 'A' WHERE Building = 'Building2';
UPDATE OperationEntry SET building = replace(building,'Building','Bldg') WHERE building = 'Building5';
UPDATE OperationEntry SET building = building||'X', company = company||'X' WHERE company = 'company1' AND building = 'Building3';

-- Show the data post updates
SELECT * FROM OperationEntry;
SELECT * FROM OperationEntryChanges;
-- Show the changes made
SELECT 
  datetime(timestamp),
    updatecounter,
    CASE 
      WHEN oldcompany <> newcompany AND oldbuilding <> newbuilding THEN 'Company changed from '|| oldcompany || ' to ' || newcompany || ', also Building changed from ' || oldbuilding || ' to ' || newbuilding
        WHEN oldcompany <> newcompany THEN 'Company changed from '|| oldcompany || ' to ' || newcompany 
      WHEN oldbuilding <> newbuilding THEN 'Building changed from ' || oldbuilding || ' to ' || newbuilding END AS changemade
FROM OperationEntryChanges
;

Следующие результаты будут: -

Результат 1

Таблица ядра после загрузки данных: -

enter image description here

Результат 2

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

enter image description here

Результат 3

Измененная основная таблица (изменения выделены)

enter image description here

Результат 4

Таблица журнала изменений (после всех 5 обновлений (изменилось 6 значений))

![enter image description here

Результат 5

Изменения, сделанные в более удобном для использования формате

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...