2012-05-08 2 views
0

Я использую сессионного компонента ж/в EXTENDED контексте постоянства, и следующие настройки: @TransactionAttributeсохранялось объект не извлекается запрос, пока не совершат

@Stateful(...) 
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) 
public class StatefulExtendedEJBBea { 
    @PersistenceContext(unitName = "JPAModel", type = PersistenceContextType.EXTENDED) 
    private EntityManager em; 

    ... 

    /** 
    * With the REQUIRED txn attribute, we can ensure that each time 
    * this method is called a new transaction is created and any 
    * pending changes in the persistence context are committed. 
    */ 
    @TransactionAttribute(TransactionAttributeType.REQUIRED) 
    public void commitTransaction() { 
    } 

    /** <code>select o from Departments o</code> */ 
    public List<Departments> getDepartmentsFindAll() { 
     return em.createNamedQuery("Departments.findAll").getResultList(); 
    } 

    public <T> T persistEntity(T entity) { 
     em.persist(entity); 
     return entity; 
    } 
} 

Некоторые важные вещи, чтобы вызвать в этом примере :

  1. TXN не начато, когда метод persistEntity() вызывается, из-за фасоли уровня @TransactionAttribute (NOT_SUPPORTED) настройки.
  2. Txn только начинается и завершается, когда вызывается метод commitTransaction(), потому что он аннотируется @TransactionAttribute (ТРЕБУЕТСЯ).

Такой подход позволяет новым компаниям сохраняться (и их идентификаторы сгенерирован и автоматически присваиваемый JPA, используя @GeneratedValue) без JPA жадностью выдачи ВСТАВИТЬ STMT в БД. Следовательно, я могу сохранить объект сразу, прежде чем назначать значения свойств, потому что ограничения NOT NULL столбца еще не проверены. Только когда вызывается метод commitTransaction(), JPA выполняет INSERT stmt и выполняет COMMIT.

Теперь, похоже, работает так, как я ожидал, с перечисленными выше преимуществами. Проблема, с которой я сталкиваюсь, заключается в том, что я не могу получить новые постоянные объекты через запрос JPQL до тех пор, пока не будет вызвана commitTransaction(). Новые сохраняемые объекты, как представляется, управляются контекстом персистентности, потому что я могу продолжать их обновлять после вызова persistEntity(), и все последующие изменения должным образом сохраняются в БД при вызове commitTransaction(). Тем не менее, они не отображаются в кэше запросов, пока я не выдаю коммит.

Я предполагаю, что моя стратегия подавления txn до момента фиксации влияет на результаты запроса каким-то образом.

Есть подсказка для запроса, которую я могу использовать для принудительного сохранения (за пределами транзакции), но не завершенных объектов, которые должны быть включены в запросы JPQL?

TIA

+0

Запросы всегда идут в базу данных. Если ваши объекты не находятся в базе данных, они не будут найдены по вашему запросу. –

+0

Итак, когда JPA выполняет JPQL stmt, он выдает предварительный запрос для извлечения только значений PK? Затем он выполняет итерации по этим значениям PK, находит какие-либо сущности в своем кеше, которые соответствуют, и выдает только полный запрос с предложением where - список ПК, которые не были найдены? –

+0

Это более или менее то, что происходит, когда у вас есть кеш второго уровня и кеш запросов, с Hibernate (не знаю других реализаций). Но я не понимаю, что это касается вашего вопроса. –

ответ

1

Вы можете вызвать flush() для записи изменений в базу данных до фиксации.

See, http://en.wikibooks.org/wiki/Java_Persistence/Persisting#Flush

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

Смежные вопросы