Как JPA управляет объектами во всех одинаковых экземплярах приложения? - PullRequest
0 голосов
/ 31 августа 2018

У меня есть некоторые запутанные вещи о JPA.

Насколько я знаю, JPA имеет контекст персистентности (он же кеш L1) и управляет всеми объектами для персистентности. и управляет сущностью с помощью описанного ниже процесса.
1. когда происходит запрос на поиск, в контексте отсутствует сущность, поэтому менеджер сущностей запрашивает данные в базе данных
2. сохранить результат как сущности в постоянном тексте.
3. после этого, когда запрос происходит, запрос постоянства возвращает объекты памяти, если они есть.

Но в-третьих, это довольно запутанно, как это работает в среде нескольких экземпляров. Я думаю, что в нескольких экземплярах приложения он не может обеспечить одинаковые данные сущности во всех экземплярах.

Предположим, что есть 2 экземпляра приложения JPA (все экземпляры имеют одинаковую логику для распределения нагрузки). Таблица имеет 2 столбца, один - id, первичный ключ, а другой - имя varchar.

Есть строка с id = 1, name = "foobar"

«экземпляр A» генерирует сущность с идентификатором, равным 1, из базы данных по запросу пользователя.
также "экземпляр B" генерирует ту же сущность с идентификатором, равным 1, из базы данных по запросу пользователя.
и затем «экземпляр A» обновляет объект с ID = 1 до name = «blahblah» по запросу пользователя на обновление.

По прошествии достаточного количества времени спустя без запроса к обоим экземплярам, ​​если запрос на обновление, который представляет собой «имя обновления, устанавливает новое имя из таблицы, где name = blahblah», возникает в «экземпляре B», я запутался, у него уже есть сущность и ее имя не может быть обновлено до «бла». Итак, как работает последний запрос на обновление в JPA?

EDIT Я понял, что мой вопрос не ясен. Поскольку JPA выполняет запрос БД к СУБД, когда транзакция была принята, обычно не возникает проблем с количеством приложений.

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

void updateEntities() {
  entityManager.getTransaction().begin();
  List<MyEntity> entities = dao.findAll(); // point1
  for (MyEntity e : entities) {
    e.setValue(e.getValue() + 100); // point2
  }
  entityManager.getTransaction().commit();
}

List<MyEntity> findMyEntities() {
  return dao.findAll(); // point3
}

Два экземпляра, в коде которых есть вышеуказанный блок кода (оба являются одинаковыми экземплярами кода для распределения нагрузки). (а количество объектов достаточно для оперативной памяти.)

когда A instance генерирует сущности в памяти, когда по запросу клиента вызывается метод findMyEntities.
затем следующий запрос был получен клиентом, затем запрос достиг instance B, и instance B также сгенерировал все объекты в памяти. а затем запрос на обновление достиг instance A, и экземпляр, выполняющий updateEntities, и все объекты в памяти instance A были обновлены.
но в это время, есть разница между кэшированными объектами instance A и instance B кэшированными объектами. Но instance B может не знать, были ли обновлены данные, или нет.

Так что мне стало интересно, когда запрос на обновление произойдет до instance B после описанной выше ситуации, я считаю, как показано ниже

  1. запрос пользователя произошел. поэтому будет вызван метод updateEntities.
  2. в точке 1, JPA немедленно выполнила реальный запрос для дБ и синхронизировала результат запроса с контекстом объекта.
  3. кодовый блок point2 выполняется нормально.

Это правильно?

Ответы [ 3 ]

0 голосов
/ 31 августа 2018

Класс бобов, обычно помечается:

@ Stateless без статуса, то есть не сохраняет состояние, даже если другой бин запрашивает ту же информацию.

Вы можете прочитать:

https://www.tutorialspoint.com/ejb/ejb_stateless_beans.htm

@ StateFul со статусом сохранит состояние и не изменится, пока компонент не завершит транзакцию.

Вы можете прочитать:

https://www.tutorialspoint.com/ejb/ejb_stateful_beans.htm

И прочитайте это:

https://docs.oracle.com/javaee/6/tutorial/doc/gipjg.html

В дополнение к этому у вас могут быть методы (через EntityManager и EntityTransaction):

  • Откат

  • вровень

  • обновить

  • совершить

  • setFlushMode (), который может иметь два значения, AUTO и COMMIT

См. Пример:

EntityManager em = ....
EntityTransaction et = em.getTransaction();
et.begin();
try{
  em.persist(someObject);
  et.commit();  
}

et.rollback();

Наконец, вы можете указать тип транзакции, которую вы хотите использовать в вашем бине, это может быть:

  • ОБЯЗАТЕЛЬНО

  • ТРЕБУЕТСЯ

  • REQUIRES_NEW

  • ОПОРЫ

  • NOT_SUPPORTEED

  • НИКОГДА НЕ

Чтобы использовать этот атрибут:

@TransactionAttribute(TransactionAtributeType.NEVER)
  public float division(float a,float b){
    return (a/b);
  }
0 голосов
/ 04 сентября 2018

Этот вопрос возник из-за моего недопонимания по поводу срока службы кэша JPA L1.

Кэш L1 становится недействительным, когда транзакция была подтверждена или запрос клиента был завершен (в OSIV).

Итак, на мой взгляд, кэш L1 не используется совместно с потоком или процессом.
Это действительно только та же транзакция или тот же запрос в OSIV.

Так что нет проблем, если экземпляров несколько или нет.

Я ценю того, кто ответил на глупый вопрос.

0 голосов
/ 31 августа 2018

Это касается изоляции транзакции и блокировки. Если вы хотите увидеть изменения, зафиксированные другими транзакциями, необходимо обновить (сущность). JPA не знает об изменениях, совершенных другими транзакциями.

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