Как избежать конфликта ID при использовании NHibernate, но таблица базы данных также обновляется внешне? - PullRequest
1 голос
/ 09 декабря 2011

Я использую NHibernate, использую сопоставление XML.База данных ORACLE.У объекта клиента есть что-то вроде этого

<class name="CustomerEntity" table="CUSTOMER">
    <id name="Id" column="ID" type="int">
      <generator class="sequence">
        <param name="sequence">CUSTOMER_ID</param>
      </generator>
    </id>
    ... (something)
 </class>

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

В настоящее время я обманываю его, заставляя последовательность начинаться с очень высокого значения (например, 10000), так что маловероятно, чтобы числа, сгенерированные последовательностью, были такими же, как числа, введенные пользователями (естественно, они будут вводить что-то вроде 1, 2, 100 и т. Д.).Однако это все еще рискованно и не чисто.

Как решить эту проблему?Должен ли я поставить try-catch-repeat во все коды?Обратите внимание, что это все еще может вызвать проблемы, такие как очень длинный цикл, если уже используется много следующих чисел.

Ответы [ 2 ]

5 голосов
/ 09 декабря 2011

Если пользователи обновляют БД напрямую, они действительно, действительно также должны использовать эту последовательность.То есть,

INSERT (id, a, b, ...) VALUES (seq.nextval, 'bla', 'blo', ) INTO SOMETABLE

Если они этого не делают, вы действительно ничего не можете сделать, чтобы избежать столкновений.

Вы могли бы проверить наличие "занятых" идентификаторов, прочитав все идентификаторы (SELECT MAX(ID) FROM SOMETABLE), а затем изменить последовательность, чтобы начать выше этого, но, конечно, это работает, пока некоторые пользователи не входят в другойзапись.

Перед каждой операцией можно проверять «свободный идентификатор», но это, вероятно, будет слишком медленным.

Я вижу только два реальных решения:

  • Убедитесь, что все вставки используют последовательность для генерации идентификаторов.Возможно, напишите хранимую процедуру для использования пользователями или какую-нибудь вспомогательную программу ...
  • Используйте UUID в качестве идентификатора вместо целого числа.Это, конечно, требует изменения схемы.

И кстати: зачем вашим пользователям прямой доступ к БД?Это кажется мне очень необычным (и опасным по многим причинам, одна из которых вы описываете).Подумайте, как-то контролировать / опосредовать доступ, предоставляя некоторый интерфейс или, по крайней мере, некоторые хранимые процедуры.В противном случае обучение пользователей кажется вашим единственным вариантом ...

2 голосов
/ 09 декабря 2011

Вы можете получить триггеры для обработки первичного ключа, тогда вы можете забыть о заполнении первичного ключа.(аналогично автоинкрементному столбцу)

например:

CREATE OR REPLACE TRIGGER trg_customer_seq
    BEFORE INSERT
    ON customer
    FOR EACH ROW
DECLARE
BEGIN
    SELECT seq_customer_id.NEXTVAL
    INTO :NEW.ID
    FROM DUAL;
END;

Примечание: если вы используете 11g, теперь вы заменяете

SELECT seq_customer_id.NEXTVAL
INTO :NEW.ID
FROM DUAL;

на

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