Обновление EJB 3.0, затем Select не работает должным образом jboss5.1.0.G - PullRequest
2 голосов
/ 21 ноября 2011

У меня очень странная проблема. Моя проблема в том, что это

ПЕРВЫЙ выбираю объект из базы данных, используя EJB 3.0 и jboss 5.1.0.GA

Subscriber s = (Subscriber)manager.createQuery("SELECT s FROM Subscriber s " +
        "WHERE s.subscriber_id = ?1").setParameter(1,123).getSingleResult();

Затем я делаю обновление сущности с запросом, подобным этому

int a  = manager.createQuery(" UPDATE Subscriber s SET s.balance = s.balance + "+10+"WHERE s.subscriber_id = ?1").setParameter(1,123).executeUpdate();

ПОТОМ, когда я выбираю сущность, подобную этой

s = (Subscriber)manager.createQuery("SELECT s FROM Subscriber s " +
"WHERE s.subscriber_id = ?1").setParameter(1,123).getSingleResult();

НО Я не получаю обновленное значение поля «баланс» НО, как только я комментирую первый оператор SELECT, я получаю обновленное значение. Но мне нужно первое SELECT утверждение в любом случае, потому что я хочу его использовать.

Может кто-нибудь сказать мне, почему это происходит и каково его решение?

1 Ответ

1 голос
/ 21 ноября 2011

Держу пари, что это из-за проблемы с кешем.

Я предполагаю, что ваш manager является экземпляром EntityManager.

Вы выполняете первый запрос, поэтому PersistenceContext выбирает сущность Subscriber из базы данных.и кладет его в кеш.Затем вы выполняете пакетный запрос UPDATE , который напрямую попадает в базу данных, пропуская структуры кэша, поэтому он не влияет на PersistenceContext.
В конце вы снова выполняете запрос SELECT.При этом PersistenceContext проверяет, кешируется ли где-нибудь сущность Subscribe.Это так, поэтому он не попадает в базу данных, но возвращает значение, хранящееся в ее кэше.

Я не совсем понимаю, почему вы выполняете пакетный запрос UPDATE вместо простого обновлениясостояние вашего объекта и разрешение JPA фиксировать изменения, когда это уместно.

Поэтому вместо:

int a  = manager.createQuery("UPDATE Subscriber s SET s.balance = s.balance +
                             "+10+"WHERE s.subscriber_id = ?1")
                .setParameter(1,123).executeUpdate();

вы можете просто сделать:

// 's' is the Subscribe entity previously fetched from the database
s.setBalance(s.getBalance() + 10);

Хотя, если вывсе же действительно нужно , чтобы использовать bach UPDATE, тогда вы можете попробовать сделать

manager.refresh(s);

после пакетного запроса UPDATE.Это позволит JPA получить доступ к базе данных вместо ее кешированной версии.

Если вы прокомментируете первый оператор SELECT, пример работает, потому что PersistenceContext не кеширует вашу сущность.Он получает его из базы данных в первый раз сразу после пакетного запроса UPDATE.

...