114 votes

Quand utiliser EntityManager.find () vs EntityManager.getReference ()

J'ai rencontré une situation (qui je pense est bizarre mais il se peut tout à fait normal) où j'utilise l'EntityManager.getReference(LObj.getClass(), LObj.getId()) pour obtenir une base de données d'entité et de passer ensuite l'objet retourné pour être conservées dans une autre table.

Donc, fondamentalement, le flux était comme ça:

classe TFacade{

 createT(FObj, AObj) {
 T TObj = new T();
TObj.setF(FObj);
TObj.setA(AObj);
...
L'EntityManager.persist(TObj);
...
 L LObj = A. getL();
FObj.setL(LObj);
FFacade.editF(FObj);
}
}

@TransactionAttributeType.REQUIRES_NEW
classe FFacade{

editF(FObj){
 L LObj = FObj.getL();
 LObj = EntityManager.getReference(LObj.getClass(), LObj.getId());
...
L'EntityManager.de fusion(FObj);
...
 FLHFacade.créer(FObj, LObj);
}
}

@TransactionAttributeType.REQUIS
classe FLHFacade{

 createFLH(FObj, LObj){
 FLH FLHObj = new FLH();
FLHObj.setF(FObj);
FLHObj.setL(LObj);
....
L'EntityManager.persist(FLHObj);
...
}
}

J'ai été faire la suite de "l'exception java.lang.IllegalArgumentException: entité Inconnue: com.mon.la persistance.L$$EnhancerByCGLIB$$3e7987d0"

Après la regarde pendant un moment, j'ai finalement compris que c'était parce que j'étais à l'aide de l'EntityManager.getReference() la méthode que j'étais l'exception ci-dessus que la méthode était de retour d'un proxy.

Cela me fait me demander, quand est-il conseillé d'utiliser l'EntityManager.getReference() la méthode la place de l'EntityManager.méthode find() ?

L'EntityManager.getReference() renvoie une EntityNotFoundException si il ne trouve pas l'entité recherchée qui est très pratique en elle-même. L'EntityManager.méthode find() ne fait que retourner la valeur null si il ne trouve pas l'entité.

En ce qui concerne les limites de transaction, me semble que vous devez utiliser la méthode find() avant de passer à la toute nouvelle entité à une nouvelle transaction. Si vous utilisez le getReference() la méthode alors vous seriez probablement se retrouver dans une situation similaire à la mienne avec l'exception ci-dessus.

165voto

Arthur Ronald Points 19001

J'ai l'habitude d'utiliser getReference méthode lorsque je n'ai pas besoin d'accéder à la base de données de l'état (je parle de méthode de lecture). Juste pour changer d'état (je parle de méthode de définition). Comme vous le savez déjà, getReference retourne un objet proxy qui utilise une fonctionnalité puissante appelée automatique sale vérification. Supposons que la suite

public class Person {

    private String name;
    private Integer age;

}


public class PersonServiceImpl implements PersonService {

    public void changeAge(Integer personId, Integer newAge) {
        Person person = em.getReference(Person.class, personId);

        // person is a proxy
        person.setAge(newAge);
    }

}

Si je l'appelle de trouver la méthode, JPA fournisseur, derrière les coulisses, fera appel à

SELECT NAME, AGE FROM PERSON WHERE PERSON_ID = ?

UPDATE PERSON SET AGE = ? WHERE PERSON_ID = ?

Si je l'appelle getReference méthode, JPA fournisseur, derrière les coulisses, fera appel à

UPDATE PERSON SET AGE = ? WHERE PERSON_ID = ?

Et vous savez pourquoi ???

Lorsque vous appelez getReference, vous obtiendrez un objet proxy. Quelque chose comme ceci (JPA fournisseur se charge de la mise en œuvre de la présente procuration)

public class PersonProxy {

    // JPA provider sets up this field when you call getReference
    private Integer personId;

    private String query = "UPDATE PERSON SET ";

    private boolean stateChanged = false;

    public void setAge(Integer newAge) {
        stateChanged = true;

        query += query + "AGE = " + newAge;
    }

}

Donc, avant de validation de transaction, fournisseur JPA va voir stateChanged drapeau afin de mettre à jour OU NON de la personne morale. Si aucune ligne n'est mis à jour après mise à jour de la déclaration, JPA fournisseur de jeter EntityNotFoundException selon la spécification JPA.

en ce qui concerne,

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X