JPA, объем и автосохранение? - PullRequest
1 голос
/ 15 марта 2010

Я использую JPA и, скажем, я делаю что-то вроде этого

public class MoRun extends Thread {...
public void run() {
    final EntityManagerFactory emFactory = Persistence.createEntityManagerFactory("pu");
    EntityManager manager = emFactory.createEntityManager();
    manager.setFlushMode(FlushModeType.COMMIT);
    someMethod(manager);
    ...
}


public void someMethod(EntityManager manager){
    Query query = manager.createNamedQuery("byStates");
    List<State> list = query.getResultList(); 
    for (State state : list) {
        if(someTest)
            state.setValue(...)
    }
...
}

Таким образом, для тех объектов, которые проходят «someTest» и значения обновляются, эти изменения автоматически сохраняются в БД, даже если транзакции отсутствуют, и я явно не «manager.save (state)» для объекта? Я спрашиваю, потому что кажется, что это так, и мне было интересно, делает ли это флеш?

Ответы [ 2 ]

1 голос
/ 16 марта 2010

Согласно javadoc FlushMode (я предполагаю, что это вопрос JPA 1.0), и как указал @Konrad:

Если транзакция не активна, поставщик сохраняемости не должен сбрасываться в базу данных.

Поскольку вы, скорее всего, используете transaction-type="RESOURCE_LOCAL" в качестве единицы измерения персистентности, поскольку я не вижу никаких begin / commit, окружающих ваши звонки на EntityManager (что не очень хорошо, подробнее об этом только после), для меня нет активной транзакции, поэтому я не ожидал, что что-то будет сброшено.

Во всяком случае, как напомнили в хороших JPA Concepts страница:

  • С <persistence-unit transaction-type="RESOURCE_LOCAL"> Вы несете ответственность за EntityManager (PersistenceContext / Cache) создание и отслеживание ...
    • Вы должны использовать EntityManagerFactory, чтобы получить EntityManager
    • Полученный EntityManager экземпляр является PersistenceContext / Cache
    • EntityManagerFactory можно вводить через @PersistenceUnit только аннотация (не @PersistenceContext)
    • Вы не разрешено использовать @PersistenceContext для ссылки на юнит типа RESOURCE_LOCAL
    • You должен использовать API EntityTransaction, чтобы начать / зафиксировать каждый вызов вашего EntityManger
    • Calling entityManagerFactory.createEntityManager() дважды приводит к двум отдельным Экземпляры EntityManager и для этого два отдельных постоянных контекста / кэша.
    • Это почти никогда хорошая идея иметь более одного экземпляра EntityManager используется (не создавайте второй, если вы не уничтожили первый)

Так что, на мой взгляд, вы должны исправить свой код здесь, нет никакого смысла задаваться вопросом о неожиданном поведении, если ваш код не верен. Просто выполняет звонки на ваш EntityManager внутри транзакции.

0 голосов
/ 15 марта 2010

Откуда вы знаете, что нет транзакции? Вы используете его из EJB? В этом случае я держу пари, что есть транзакция.

Из документов (http://java.sun.com/javaee/6/docs/api/javax/persistence/FlushModeType.html):

Если установлено значение FlushModeType.COMMIT, эффект обновлений, сделанных для объектов в постоянный контекст при запросах не указано.

Если нет активной транзакции, поставщик постоянства не должен сбрасывать база данных.

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

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