Когда EntityManager фиксирует? - PullRequest
4 голосов
/ 26 октября 2011

У меня есть следующий сервис ...

@Stateless
@LocalBean
public class RandomService {

    @EJB RandomString stringTokenizer;

    @PersistenceContext
    EntityManager em;

    public String generate(Actions action)
    {
        Token token = new Token();
        token.setAction(action);
        token.setExpiry(new Date());
        token.setToken(stringTokenizer.randomize());

        em.persist(token);
        //em.flush();

        return String.format("%010d", token.getId()) + token.getToken();
    }
}

Если я не поставлю em.flush (), тогда строка token.getId () вернет ноль (используя DB GENERATED SEQUENCE), хотя я знаюесли я возвращаю токен вместо строки вызывающей службе, то идентификатор устанавливается.Таким образом, кажется, что EM сбрасывается, когда служба возвращает маркерный объект, но не когда я помещаю String.Ставя флеш, я получаю то, что мне нужно, верно?

1 Ответ

7 голосов
/ 26 октября 2011

Не путайте промывку с фиксацией.Во время flush() поставщик JPA физически отправляет сгенерированный SQL в базу данных и, в вашем случае, читает сгенерированный идентификатор и заполняет его в компоненте. Обратите внимание, что вы всегда должны использовать возвращенную сущность, а не исходную, переданную persist():

token = em.persist(token);

С другой стороны, фиксация выполняет базу данныхсовершить.Очевидно, сначала это вызовет flush(), но здесь вам это не поможет.Но так как вы спрашиваете - каждый метод в EJB является транзакционным по умолчанию.Это означает, что транзакция фиксируется, когда вы оставляете первый EJB в стеке: если вы вызываете один EJB из другого, вызываемый объект присоединяется к транзакции вызывающего по умолчанию (см .: Поведение распространения транзакции ).

Также обратите внимание, что правила для flush() немного сложны, так как каждый провайдер пытается сделать это как можно позже и партиями.

...