JPA - Returning an auto generated id after persist()

sura2k picture sura2k · Mar 16, 2012 · Viewed 130.2k times · Source

I'm using JPA (EclipseLink) and Spring. Say I have a simple entity with an auto-generated ID:

@Entity
public class ABC implements Serializable {
     @Id
     @GeneratedValue(strategy=GenerationType.IDENTITY)
     private int id;

     // ...
}

In my DAO class, I have an insert method that calls persist() on this entity. I want the method to return the generated ID for the new entity, but when I test it, it returns 0 instead.

public class ABCDao {
    @PersistenceContext
    EntityManager em;

    @Transactional(readOnly=false)
    public int insertABC(ABC abc) {
         em.persist(abc);
         // I WANT TO RETURN THE AUTO-GENERATED ID OF abc
         // HOW CAN I DO IT?
         return abc.id; // ???
    }
}

I also have a service class that wraps the DAO, if that makes a difference:

public class ABCService {
    @Resource(name="ABCDao")
    ABCDao abcDao;

    public int addNewABC(ABC abc) {
         return abcDao.insertABC(abc);
    }
}

Answer

JB Nizet picture JB Nizet · Mar 16, 2012

The ID is only guaranteed to be generated at flush time. Persisting an entity only makes it "attached" to the persistence context. So, either flush the entity manager explicitely:

em.persist(abc);
em.flush();
return abc.getId();

or return the entity itself rather than its ID. When the transaction ends, the flush will happen, and users of the entity outside of the transaction will thus see the generated ID in the entity.

@Override
public ABC addNewABC(ABC abc) {
    abcDao.insertABC(abc);
    return abc;
}