JPA путаница (управляемые против неуправляемых объектов) - PullRequest
8 голосов
/ 15 сентября 2011

Я работаю над веб-проектом, пытаясь понять, как сделать это снова и снова:

  • Чтение объекта A из БД
  • Позже, прочитайте другой объект ( B )
  • Внесите изменения в A и B в БД (какчасть транзакции - напишите все изменения или их нет)

Путь типа JDBC старого skool не является проблемой, но JPA решает мою задачу.

Мне нужно четко разграничить, где происходят изменения в БД, и из того, что я наблюдал, любые изменения в управляемых объектах будут изменены при следующем вызове EntityManager.commit() (независимо от транзакциибыл явно начат до изменений или нет).Верно?

Лучше ли быть уверенным, что все сущности никогда не управляются и всегда merge()?

Мне приходится выбирать между этими двумя примерами:

RepaintAction1

User user = getUser(); //non-managed entity
Car car = getCar(123); //non-managed

car.setColor("Red");
user.setLog("Paints car red");

dao.update(car, user);

RepaintDAO1

entityTransaction.begin();
entityManager.merge(car);
entityManager.merge(user);
entityTransaction.commit();

Или:

RepaintAction2 (это то же самое, что и RepaintAction1 , но с управляемыми сущностями)

User user = getUser(); //managed entity
Car car = getCar(123); //managed

car.setColor("Red");
user.setLog("Paints car red");

dao.update(car, user);

RepaintDAO2

entityTransaction.begin();
entityManager.flush();
entityTransaction.commit();

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

Но это единственные варианты (например, есть ли способ четко разграничить транзакции, используяуправляемые объекты)?Каков наилучший способ справиться с этим?

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

Ответы [ 2 ]

11 голосов
/ 17 сентября 2011
  1. Любые изменения в управляемых объектах будут изменены при следующем вызове EntityManager.commit() (независимо от того, была ли транзакция явно начата до изменений или нет). Правильно? Правильно.

  2. Лучше ли быть уверенным, что все сущности никогда не управляются и всегда merge()? Не всегда (или они не оставили бы выбор открытым), но это обычно, так что пример 1 - это то, что вы найдете в основном.

  3. Сброс в примере 2 на самом деле не нужен, фиксация будет выполняться неявно.

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

  5. Преимущества управляемых объектов? Ленивая загрузка (без LazyInitializationException). Кроме того, он отслеживает то, что изменилось для вас, поэтому вы не объединяете слишком много / мало объектов.

  6. Есть ли способ четко разграничить транзакции с использованием управляемых объектов? Мне не ясно, что вам не понятно. Возможно, вы имеете в виду, что непонятно видеть, что изменилось, потому что изменения в сущностях происходят за пределами границ начала / фиксации. Но это верно и для слияния отдельных сущностей, у вас есть немного больший контроль над тем, что вы объединяете, но вы не видите точно, какие атрибуты изменены.

  7. Какой лучший способ справиться с этим? Как правило, ваши веб-запросы обрабатываются службой, которая является транзакционной (spring / ejb ...). Менеджеры сущностей будут введены контейнером. Как правило, эти менеджеры сущностей находятся в области транзакции (действительны только на время транзакции), поэтому они не существовали до вызова вашей службы. Это означает, что все объекты, переданные им, не управляются. Транзакция будет зафиксирована (или откатана) в конце службы.


Примечание: Если вы думаете об использовании управляемых объектов, это часто происходит с долгоживущими EntityManager. Если вы сделаете это, имейте в виду, что EntityManager не является потокобезопасным.

0 голосов
/ 21 июля 2015

Что касается вашего четвертого вопроса, откат можно выполнить следующими способами:

  1. Бросить исключение из метода, помеченного как @ Transactional
  2. .что он должен выполнить откат TransactionAspectSupport.currentTransactionStatus (). setRollbackOnly ();
...