2014-02-09 1 views
0

Вот что я получаю:Почему параметр не сохраняется в параметре вывода?

public User register(User u) { 
    em.persist(u); 
    System.out.println("USER id: " + u.getIduser()); // INFO: USER id: 0 
    em.flush(); 
    System.out.println("USER id: " + u.getIduser()); // INFO: USER id: 1 
    return u; 
} 

Даже если опустить вызов flush() хотя пользователь это сохраняется в БД (MySQL, я использую glasssfish 4 из затмения). Так почему мне нужно вызвать flush, чтобы установить id (он автоматически вызывается, по-видимому, на выходе метода, но говорят, что я хотел использовать идентификатор, находясь в register())?

Как в стороне, вызывает ли факт, что флеш() указывает на транзакцию?

Update: вот класс EJB:

@Stateless 
public class UserService { 

    @PersistenceContext 
    private EntityManager em; 

    public User register(User u) { 
     em.persist(u); 
     // em.flush(); // not needed - called on exit - maybe I have a 
     // transaction after all 
     return u; 
    } 
} 
+0

UserService вызывается из открытого сервиса UserController @ManagedBean @ViewScoped {@EJB private UserService; } '. Я думаю, наконец, что ответ на титульный вопрос заключается в том, что persist() должен быть асинхронным. –

ответ

0

Если вы проверяете the documentation for EntityManager вы можете увидеть.

аннулируются вровень()

Синхронизировать контекст сохранения в основной базе данных.

Persist() не обновляет вашу сущность, но выполняет действие в базе данных.

Чтобы получить свой идентификатор, вы должны синхронизировать свою сущность.

AFAIR flush() не имеет отношения к сделкам. Поскольку JTA управляет вашими транзакциями. JTA вызывает методы begin, commit, rollback от EntityTransaction, который возвращается EntityManager.getTransaction().

Если вы вызываете метод EntityManager.refresh на свой объект, он также должен быть синхронизирован.

EDIT

Каждый EJB управляется Java EE контейнер. Вы только что заметили эффект этого управления. Каждый вызов метода выполняется в транзакции и, вероятно, также с этой синхронизацией.

Чтобы понять, почему это происходит можно назвать:

Thread.currentThread().getStackTrace() 

В вашем UserService.register и распечатать полный набор StackTrace элементов. Вы получите что-то похожее на:

UserService.register(UserService.java:xxx) 
SomeGenerated.invoke(SomeGenerated.java:xxx) 
SomeGenerated.invoke(SomeGenerated.java:xxx) 
UserController.register(UserController.java:xxx) 

Таким образом, вы не называйте UserService.register метод непосредственно из UserController.register, как вы, возможно, ожидали.

Этот класс «SomeGenerated» заботится о контракте, который дает вам EJB. И, например, они заботятся о транзакциях и, вероятно, также в вашем случае о сущности синхронизации с базой данных.

+0

Если я просто сделаю 'em.persist (u); return u;' '' u', я вернусь, имеет правильный идентификатор, поэтому 'flush' или' refresh' вызывается при возврате метода.Я редактировал вопрос с аннотациями в моем классе - есть ли у меня транзакция, выполняемая в 'UserService .register()'? (хотя мой вопрос: _why_ persist не обновляется, я буду удовлетворен _how_ :) –

+0

Я обновил сообщение, чтобы ответить на ваш вопрос – zimi

+0

Спасибо - я видел трассировку стека и \ _ \ _ Generated \ _ без необходимости называть ' Thread.currentThread(). GetStackTrace() '(шутка), но ваш ответ имеет смысл :). Чтобы быть совершенным, мне нужны некоторые ссылки на документы по этой синхронизации. Не влияет ли @stateless на транзакции? –