web-dev-qa-db-fra.com

JPA - Renvoi d'un identifiant généré automatiquement après persist ()

J'utilise JPA (EclipseLink) et Spring. Disons que j'ai une entité simple avec un identifiant généré automatiquement:

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

     // ...
}

Dans ma classe DAO, j'ai une méthode d'insertion qui appelle persist() sur cette entité. Je souhaite que la méthode retourne l'ID généré pour la nouvelle entité, mais lorsque je la teste, elle renvoie plutôt 0.

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

J'ai également une classe de service qui enveloppe le DAO, si cela fait une différence:

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

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

L'identification n'est garantie que lors de la génération. La persistance d'une entité ne la rend que "rattachée" au contexte de persistance. Donc, soit vider explicitement le gestionnaire d'entités:

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

ou renvoyer l'entité elle-même plutôt que son identifiant. Lorsque la transaction se termine, le vidage aura lieu et les utilisateurs de l'entité extérieure à la transaction verront ainsi l'ID généré dans l'entité.

@Override
public ABC addNewABC(ABC abc) {
    abcDao.insertABC(abc);
    return abc;
}
145
JB Nizet
@Entity
public class ABC implements Serializable {
     @Id
     @GeneratedValue(strategy=GenerationType.IDENTITY)
     private int id;   
}

vérifiez que la notation @GeneratedValue figure dans votre classe d'entités. Cela indique à JPA le comportement généré automatiquement par votre propriété d'entité

10
utkal patel

Voici comment je l'ai fait:

EntityManager entityManager = getEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(object);
transaction.commit();
long id = object.getId();
entityManager.close();
3
Koray Tugay

Vous pouvez également utiliser GenerationType.TABLE au lieu de IDENTITY, qui n'est disponible qu'après l'insertion.

2
James

Voici comment je l'ai fait. Tu peux essayer

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

    public int addNewABC(ABC abc) {
         ABC.setId(0);
         return abcDao.insertABC(abc);
    }
}
0
Anh Khoa

Une autre option compatible à 4.0:

Avant de valider les modifications, vous pouvez récupérer le ou les nouveaux objets CayenneDataObject de la collection associée au contexte, comme suit:

CayenneDataObject dataObjectsCollection = (CayenneDataObject)cayenneContext.newObjects();

ensuite, accédez à la ObjectId pour chacun dans la collection, comme:

ObjectId objectId = dataObject.getObjectId();

Enfin, vous pouvez effectuer une itération sous les valeurs. Généralement, l'id-généré sera la première des valeurs (pour une clé de colonne unique) dans la carte renvoyée par getIdSnapshot(). PK comme clé (s):

objectId.getIdSnapshot().values()
0
emecas