2012-03-16 6 views
77

Estoy usando JPA (EclipseLink) y Spring. Digamos que tiene una entidad sencilla con un ID autogenerado:JPA - Devolviendo una identificación generada automáticamente después de persist()

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

    // ... 
} 

En mi clase DAO, tengo un método de inserción que llama persist() en esta entidad. Quiero que el método devuelva el ID generado para la nueva entidad, pero cuando lo pruebo, devuelve 0 en su lugar.

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

que también tienen una clase de servicio que envuelve la DAO, si eso hace la diferencia:

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

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

uno similar, puede referirse a http://stackoverflow.com/q/3328813/366964 –

+0

Gracias por las respuestas. Y como una solución difícil (no una JPA) podemos usar otra identificación única como la marca de tiempo de unix. – sura2k

+1

posible duplicado de [¿Cuándo establece el JPA un @GeneratedValue @Id] (http://stackoverflow.com/questions/9087848/when-does-the-jpa-set-a-generatedvalue-id) – Raedwald

Respuesta

121

El ID sólo se garantiza que se generen en el tiempo de descarga. Persistir una entidad solo la hace "adjunta" al contexto de persistencia. Así que, o bien eliminar el gestor de entidades explícitamente:

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

o devolver la propia entidad en lugar de su ID. Cuando la transacción finalice, se producirá la descarga, y los usuarios de la entidad que estén fuera de la transacción verán la ID generada en la entidad.

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

NB: esto necesita anotar el campo de id con '@ GeneratedValue' - lo que sea que implique –

+0

¿Puedes explicar los problemas al tratar de lograr esto con ID compuesto http://stackoverflow.com/questions/31362100/explain-behaviors-in-mapping-auto -incremented-composite-id-sequence-with-hiberna – bl3e

+0

¿Hay una penalización de rendimiento (o cualquier otro efecto negativo) de enjuague manual después de persistir? –

-1
em.persist(abc); 
em.refresh(abc); 
return abc; 
+0

Este método no funcionó para mí. Obtuve este error: javax.persistence.PersistenceException: org.hibernate.HibernateException: esta instancia aún no existe como una fila en la base de datos] – rtcarlson

+0

@rtcarlson, sí, esto no funcionará. si está creando un objeto nuevo, lo que necesita es 'em.flush()' not 'em.refresh (abc)'. –

2

También es posible usar GenerationType.TABLE en lugar de identidad, que sólo está disponible después de la inserción.

1

Esto es cómo lo hice:

EntityManager entityManager = getEntityManager(); 
EntityTransaction transaction = entityManager.getTransaction(); 
transaction.begin(); 
entityManager.persist(object); 
transaction.commit(); 
long id = object.getId(); 
entityManager.close(); 
+0

No funciona dando cero como retorno después de persistir los datos en la tabla. o la actualización no funciona en este caso ... ¿Qué debo hacer para esto? por favor sugiera una manera ... Gracias –

+0

@VikrantKashyap Por favor, publique una nueva pregunta con un código pequeño y mencióneme para que pueda echar un vistazo. –

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

cheque que la notación @GeneratedValue está allí en su entidad JPA class.This dice acerca de su propiedad entidad auto-generado comportamiento

Cuestiones relacionadas