Printemps, @Transactionnelle et Hibernate Chargement Paresseux
je suis en utilisant spring + hibernate. Tous mes HibernateDAO utiliser directement sessionFactory.
J'ai de la couche application -> couche de service -> DAO couche et toutes les collections est lazly chargé.
Donc, le problème, c'est que dans le courant de la couche d'application(qui contient GUI/swing) je charge une entité à l'aide d'une couche de service méthode(qui contient @Transactional annotation) et je veux utiliser un lazly propriété de cet objet, mais obviusly la session est déjà fermé.
Quelle est la meilleure façon de résoudre ce problème?
MODIFIER
J'essaie d'utiliser un MethodInterceptor, mon idée est d'écrire un AroundAdvice pour toutes mes Entités et utiliser les annotations, ainsi par exemple:
//Custom annotation, say that session is required for this method
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SessionRequired {
//An AroundAdvice to intercept method calls
public class SessionInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation mi) throws Throwable {
bool sessionRequired=mi.getMethod().isAnnotationPresent(SessionRequired.class);
//Begin and commit session only if @SessionRequired
if(sessionRequired){
//begin transaction here
}
Object ret=mi.proceed();
if(sessionRequired){
//commit transaction here
}
return ret;
}
}
//An example of entity
@Entity
public class Customer implements Serializable {
@Id
Long id;
@OneToMany
List<Order> orders; //this is a lazy collection
@SessionRequired
public List<Order> getOrders(){
return orders;
}
}
//And finally in application layer...
public void foo(){
//Load customer by id, getCustomer is annotated with @Transactional
//this is a lazy load
Customer customer=customerService.getCustomer(1);
//Get orders, my interceptor open and close the session for me... i hope...
List<Order> orders=customer.getOrders();
//Finally use the orders
}
Pensez vous que cela peut-il fonctionner?
Le problème est, comment s'inscrire à l'intercepteur pour toutes mes entités sans faire dans le fichier xml?
Il y a un moyen de le faire avec l'annotation?
OriginalL'auteur blow | 2010-11-17
Vous devez vous connecter pour publier un commentaire.
Hibernate récemment introduit chercher les profils (en plus de la performance tuning) est idéal pour résoudre les questions de ce genre. Il vous permet (à l'exécution) de choisir entre les différentes opérations de chargement et l'initialisation des stratégies.
http://docs.jboss.org/hibernate/core/3.5/reference/en/html/performance.html#performance-fetching-profiles
Modifier (ajout d'une section sur la façon de définir le parcours de profil à l'aide d'un intercepteur):
Avant de commencer: Vérifiez que l'extraction de profils sera effectivement travailler pour vous. Je n'ai pas utilisé moi-même et de voir qu'ils sont actuellement limitées à rejoindre les extractions. Avant de perdre du temps sur la mise en œuvre et le câblage de l'intercepteur, essayez de définir le parcours de profil manuellement et voir ce que cela résout votre problème.
Il existe de nombreuses façons pour l'installation d'intercepteurs au Printemps (selon les préférences), mais le plus simple serait de mettre en œuvre un MethodInterceptor (voir http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop-api.html#aop-api-advice-around). Laisser un setter pour l'extraction de profil que vous souhaitez et setter pour la Session Hibernate usine:
Enfin, permettre l'intercepteur dans le Ressort de config. Cela peut être fait de plusieurs façons, et vous avez probablement déjà un AOP de configuration que vous pouvez ajouter. Voir http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-schema.
Si vous êtes nouveau à l'AOP, je vous suggère d'essayer le "vieux" ProxyFactory voie d'abord (http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop-api.html#aop-api-proxying-intf) parce qu'il est plus facile de comprendre comment il fonctionne. Voici un exemple de code XML pour vous aider à démarrer:
Vous pouvez par exemple envelopper le service / dao avec un intercepteur qui définit fetch profil "gui" lorsqu'il est appelé à partir de l'interface graphique. Laissez-moi savoir si vous avez besoin de plus de détails sur cette.
assurez-vous de vous remercier, ce son intéressant.
Ajouté à la réponse.
Merci DaGGeRRz, j'ai une question simple: à ce moment j'utilise l'auto-scan pour scanner mes composants(DAOs,srvices référentiel etc...), puis-je inscrire un intercepteur pour toutes mes entités automatiquement? Je vais éditer mon premier post pour cette question.
OriginalL'auteur DaGGeRRz
(seulement alors que nous attendons pour quelqu'un qui sait de quoi ils parlent)
OriginalL'auteur willcodejavaforfood
Vous avez besoin de retravailler votre gestion de session, malheureusement. C'est un problème majeur lorsque l'on traite avec Hibernate et Spring, et c'est un énorme souci.
Essentiellement, ce que vous avez besoin pour votre application de la couche de créer une nouvelle session lorsqu'il obtient votre Hibernate objet, et de le gérer et de fermer la session correctement. Ce genre de choses est difficile, et les non-trivial, l'une des meilleures façons de gérer cela est de la médiation de la des séances travers l'usine disponibles à partir de votre couche de l'application, mais vous devez toujours être en mesure de mettre fin à la session correctement, de sorte que vous devez être conscient des besoins du cycle de vie de vos données.
Ce genre de choses est la plainte la plus commune sur l'utilisation de Spring et Hibernate de cette façon, vraiment, la seule façon de le gérer est d'obtenir une bonne poignée sur exactement ce que vos données de cycle de vie.
oui, vous pouvez, et c'est une très bonne idée, le problème est de savoir quand mettre fin à la session (c'est à dire, lorsque votre objet de la modification est terminée). Dans certains cas, c'est facile; dans d'autres, étonnamment difficile.
OriginalL'auteur Paul Sonier