60 votes

Détacher une entité du contexte de persistance JPA/EJB3

Quel serait le moyen le plus simple de détacher un Bean d'entité JPA spécifique qui a été acquis par le biais d'un EntityManager. Ou encore, pourrais-je faire en sorte qu'une requête renvoie des objets détachés dès le départ, afin qu'ils agissent essentiellement en "lecture seule" ?

La raison pour laquelle je veux faire cela est que je veux modifier les données à l'intérieur du bean - dans mon application seulement, mais sans jamais les faire persister dans la base de données. Dans mon programme, je dois éventuellement appeler flush() sur l'EntityManager, qui persisterait toutes les modifications des entités attachées à la base de données sous-jacente, mais je veux exclure des objets spécifiques.

3voto

jsight Points 16025

Pour autant que je sache, les seuls moyens directs de le faire sont :

  1. Engager le txn - Probablement pas une option raisonnable
  2. Effacer le contexte de persistance - EntityManager.clear() - C'est brutal, mais cela permet de l'effacer.
  3. Copier l'objet - La plupart du temps, vos objets JPA sont sérialisables, donc cela devrait être facile (même si ce n'est pas particulièrement efficace).

1voto

mogrify Points 383

S'il n'y a pas trop de propriétés dans le haricot, vous pouvez simplement créer une nouvelle instance et définir toutes ses propriétés manuellement à partir du haricot persistant.

Cela pourrait être mis en œuvre comme un constructeur de copie, par exemple :

public Thing(Thing oldBean) {
  this.setPropertyOne(oldBean.getPropertyOne());
  // and so on
}

Ensuite :

Thing newBean = new Thing(oldBean);

1voto

Mauricio Kanada, merci à vous pour ce conseil, la méthode evict() fonctionne bien. J'utilise JPA de SEAM, il y a un support intégré de JPA Entity Manager, et il est possible d'accéder au délégué Session d'Hibernate et donc à cette méthode "evict".

Merci beaucoup, Zmicer

1voto

davideconsonni Points 952

C'est rapide et sale, mais vous pouvez aussi sérialiser et désérialiser l'objet.

1voto

David Faulstich Points 11

Puisque j'utilise SEAM et JPA 1.0 et que mon système a une fuctinalité qui nécessite d'enregistrer tous les changements de champs, j'ai créé un objet de valeur ou un objet de transfert de données si les mêmes champs de l'entité qui doit être enregistrée. Le constructeur du nouveau pojo est :

    public DocumentoAntigoDTO(Documento documentoAtual) {
    Method[] metodosDocumento = Documento.class.getMethods();
    for(Method metodo:metodosDocumento){
        if(metodo.getName().contains("get")){
            try {
                Object resultadoInvoke = metodo.invoke(documentoAtual,null);
                Method[] metodosDocumentoAntigo = DocumentoAntigoDTO.class.getMethods();
                for(Method metodoAntigo : metodosDocumentoAntigo){
                    String metodSetName = "set" + metodo.getName().substring(3);
                    if(metodoAntigo.getName().equals(metodSetName)){
                        metodoAntigo.invoke(this, resultadoInvoke);
                    }
                }
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
}

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