Question

Here is what I get:

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;
}

Even if I omit the call to flush() though the user is persisted in the DB (MySQL, I use glasssfish 4 from eclipse). So why do I need to call flush to set the id (it is auto called apparently on method exit but say I wanted to use the id while in register()) ?

As an aside, does the fact that flush() is called indicate a transaction going on ?

Update: here's the EJB class:

@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;
    }
}
Was it helpful?

Solution

If you check the documentation for EntityManager you can see.

void flush()

Synchronize the persistence context to the underlying database.

Persist() does not refresh your entity however it executes action on database.

To get your id you have to synchronize your entity.

AFAIR flush() is not related with transactions. Since JTA manages your transactions. JTA calls methods begin, commit, rollback from EntityTransaction, which is returned by EntityManager.getTransaction().

If you invoke EntityManager.refresh method on your entity it should also be synchronized.

EDIT

Every EJB is managed by Java EE Container. You have just noticed the effect of this managing. Every method call is in transaction and probably also with this synchronization.

To see why it's happening you can call:

Thread.currentThread().getStackTrace()

In your UserService.register, and print full array of stacktrace elements. You will get something similar to:

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

So you don't call UserService.register method directly from UserController.register as you maybe expected.

This "SomeGenerated" classes take care about contract which gives you EJB. And for example they care about transactions and probably also in your case about synchronization entity with database.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top