Détacher JPA objets avec lazy initialisé propriétés
Il y a deux entités JPA: l'Utilisateur et de l'Ordre de un à plusieurs " de la relation.
/**
* User DTO
*/
@Entity
@Table(name="user")
public class User implements Serializable {
private static final long serialVersionUID = 8372128484215085291L;
private Long id;
private Set<Order> orders;
public User() {}
@Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="sequenceUser")
public Long getId() {
return this.id;
}
private void setId(Long id) {
this.id = id;
}
@OneToMany(mappedBy="user", cascade=CascadeType.PERSIST, fetch=FetchType.LAZY)
@LazyCollection(LazyCollectionOption.EXTRA)
public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
}
/**
* Order DTO
*/
@Entity
@Table(name="order")
public class Order implements Serializable {
private static final long serialVersionUID = 84504362507297200L;
private Long id;
private User user;
public Order() {
}
@Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="sequenceOrder")
public Long getId() {
return this.id;
}
private void setId(Long id) {
this.id = id;
}
@ManyToOne
@JoinColumn(name="user_id")
public User getUser(){
return user;
}
public void setUser(User user){
this.user = user;
}
}
- Je utiliser ces entités dans ma couche de service des classes où chaque méthode s'exécute dans la transaction. Tout est bien sauf cas lorsque les méthodes de la couche de service des classes doit retourner ces entités.
@Transactional(readOnly=true)
public Set<Order> getOrders() {
Set<Order> orders = user.getOrders();
return orders;
}
Cette méthode retourne les données. Mais lorsque j'essaie d'accéder à recevoir des éléments de collection à j'exception de catch: "org.mise en veille prolongée.LazyInitializationException: échec paresseusement initialiser une collection de rôle: le package.De l'utilisateur.les commandes, pas de session ou la session a été fermée".
Ainsi, il a été l'exception. Je pensais que le détachement résultat va résoudre mon problème, mais le truc comme ça
@Transactional(readOnly=true)
public Set<Order> getOrders() {
Set<Order> orders = user.getOrders();
for(Order order: orders)
entityManager.detach(order);
return orders;
}
n'a rien changé 🙁
Il n'est pas question pour moi d'infos sur les utilisateurs de suivre dans l'ensemble de commandes ou pas. Je veux juste travailler avec cet ensemble et de ne pas la modifier.
Quelqu'un peut-il m'aider? 🙂
OriginalL'auteur mikhail | 2010-09-04
Vous devez vous connecter pour publier un commentaire.
L'erreur est conviviale: vous essayez de charger un (paresseux) chargé de la collecte, mais il n'y a pas de session active plus parce que le
User
instance est détachée.Cela ne changera rien. Le
EntityManager#détacher(Objet)
méthode n'est pas charge quoi que ce soit, il supprime l'entité à partir du contexte de persistance, rendant détaché.Vous devez soit faire de l'association HÂTE (de sorte que les Commandes seront chargés lors de la récupération d'un Utilisateur) ou d'utiliser une EXTRACTION REJOINDRE lors de la récupération d'un utilisateur à votre service:
Hibernate a un
Hibernate.initialize
méthode, mais ce n'est évidemment pas la norme JPA (préférez chercher rejoindre pour portable code).Quoi? Qu'entendez-vous par les ignorer? Pourquoi voudriez-vous faire de toute façon?
Je comprends que tente d'ignorer paresseux inits est mal, mais j'ai intérêt purement académique. Par exemple, j'ai reçu un objet de la classe d'Utilisateur via le gestionnaire d'entité: "l'utilisateur Utilisateur = entityManager(User.class, 1)". En ce moment, les "ordres" de la propriété est égal à null, car il est paresseux. Est-il possible de "détacher" objet "utilisateur" de l'hibernation pour prévenir la propriété "commandes" init cours de méthode d'accès "getOrders"?
il est possible de "détacher" objet "utilisateur" de l'hibernation pour prévenir la propriété "commandes" init cours de méthode d'accès "getOrders"? de la Recherche pour "unproxy" ou "deproxy" sur l'Hibernation des forums.
Merci encore! C'est exactement ce que j'ai cherché!
OriginalL'auteur Pascal Thivent
La LazyInitialisationException se produit en raison de données est demandée en dehors d'une transaction. Si vous avez besoin que les données, vous devez vous adresser au sein d'une transaction - dans votre cas, ce serait à l'intérieur de la méthode de service.
Vous pouvez demander les données à charger dans plusieurs façons. Le plus simple:
(où X est un bien autre que de l'Id ou de la version)
Ce sera cependant la charge de chaque commande dans une autre requête, qui est trop lent si il y a beaucoup de commandes. Une rapide approche consisterait à émettre une requête (JP-QL ou Critères) le retour de tous les ordres de l'utilisateur. (Edit: Voir Pascal, en réponse à une requête.)
OriginalL'auteur meriton