транзакция гибернации (чтение одной строки как inprog, запись в другую таблицу) (чтение другой таблицы, установка строки в notinprog) - PullRequest
0 голосов
/ 15 января 2011

Я новичок в спящем режиме и транзакциях.

У меня есть строка в таблице, которая помечает ее как текущее состояние.У меня есть вторая таблица, которая используется для записи строк, которые должны быть получены незавершенным работником непосредственно перед его завершением, и это эффективно добавляет к его рабочему списку.

Есть 2 транзакции, которые используют эти2 таблицы:

1) транзакция выбирает текущую фиктивную строку для столбца максимального порядкового номера.Когда он видит этот ряд, он должен знать, что этот ряд был зафиксирован.(Какова минимальная изоляция?) Затем он проверяет, является ли флаг выполнения строки истинным.Если выполняется, он знает, что существует другой длительный поток (не единственная транзакция), который уже зафиксировал эту строку в процессе, и он добавляет свой новый фрагмент данных во вспомогательную таблицу, ожидая, что долгосрочныйработающий поток получит / удалит / обработает строки из вспомогательной таблицы, сделает с ними что-то и, наконец, установит для inprogress значение false в одной атомарной транзакции.

2) второй поток запускается и видит, что выполняетсястремится к истине с самого начала.Он выполняет несколько частей в отдельных транзакциях.Затем он выполняет одну заключительную атомарную транзакцию: (1) считывает вспомогательные данные, которые несколько потоков 1 (и) записали во вторую таблицу, (2) удаляет их и обрабатывает их, (3) записывает незавершенный столбецстрока прогресса равна false.

Мой первый вопрос для этих двух связанных транзакций: какие минимальные уровни изоляции мне нужны, чтобы заставить их работать должным образом, когда по окончании потока 2 он обработает все вспомогательные данные, которыепоток 1 добавляется во вторую таблицу B, когда он видит состояние in-progess.

Кроме того, я очень обеспокоен тем, что когда я использую средство настройки гибернации, чтобы установить состояние выполнения в false в потоке 2), этоЯ должен сделать это ДО извлечения, удаления и обработки вспомогательных данных.И что, делая это первым в транзакции, я должен также сбросить сессию, чтобы перейти в спящий режим, чтобы вызвать изоляцию?

Спасибо, Энди

1 Ответ

0 голосов
/ 15 января 2011

Мне кажется, что ключ заключается в том, чтобы заблокировать строку с вашим текущим флагом, что по сути эквивалентно синхронизации с ним в терминах Java.Вы должны последовательно делать это в первую очередь до (или одновременно) чтения других данных.Можно использовать уровень изоляции с фиксацией для чтения.

Вы можете заблокировать строку, указав LockMode.UPGRADE (или LockOptions.UPGRADE Я думаю, что она изменена на 3.5) на Hibernate при получении строки из запроса или изсессия.Если вы используете собственный запрос SQL, вам придется использовать реализацию базы данных (обычно ... FOR UPDATE).Например:

StatusData status = (StatusData) session.get(StatusData.class, id, LockOptions.UPGRADE);

, который Hibernate будет использовать для создания SELECT s_.id, ... FROM status_data s_ WHERE s_id = ? FOR UPDATE OF s_ или соответствующего эквивалента для вашего диалекта (например, with(updlock,rowlock))

Istr вы также указываете это в запросе, так что, вероятно,что-то вроде:

StatusData status = (StatusData)
  session.getNamedQuery("Status.FindLatest")
         .setLockMode("status", LockMode.UPGRADE)
         .uniqueResult();

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

Я полагаю, вы нашли документацию по использованию транзакций с Hibernate?http://docs.jboss.org/hibernate/core/3.3/reference/en/html/transactions.html

У меня был хороший опыт использования декларативных границ транзакций.Таким образом, DAO / EJB / что угодно для выполнения взаимодействия с базой данных, предоставляемое через интерфейс, и декоратор для автоматического запуска / принятия / отката всех вызовов через этот интерфейс.Контейнеры Spring и J2EE предоставляют инфраструктуру для этого, хотя это также легко сделать вручную.Это проясняет в коде, какие биты находятся внутри транзакции базы данных, а какие нет.Поэтому, если вы сделаете эквивалент:

void finishProcessing() {
   Session session = sessionFactory.openSession();
   Transaction tx = session.beginTransaction();
   ThreadLocalSessionContext.bind(session);
   boolean committed = false;
   try {
       underlying.finishProcessing();
       tx.commit();
       committed = true;
   } finally {
       if (!committed) tx.rollback();
       session.close();
       ThreadLocalSessionContext.unbind(sessionFactory);
   }
}

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

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