8
votes

Configuration de la session hibernate avec le ressort AOP

J'ai une application Spring Cadre 4 qui utilise Hibernate 4.3.8 en tant que fournisseur JPA. Je souhaite utiliser des filtres hibernate et donc je dois leur permettre. Je veux le faire globalement dans l'application, que j'essaie de faire avec le Spring AOP. L'idée est que je puisse écrire un aspect qui permet aux filtres chaque fois qu'une session est créée / récupérée, comme dans Ceci et Cette question.

J'ai ajouté le Spring-aop code> et aspectJweaver code> dépendances à mon projet (à l'aide de Maven). J'ai ajouté l'aspect suivant. P> xxx pré>

Mon problème est que le conseil ci-dessus ( activerFilters code>) n'est jamais invoqué; Ni le texte n'est imprimé, ni mon filtre n'est activé. J'ai vérifié que mon aspect est détecté et que AOP fonctionne dans mon projet en modifiant la pointe de l'une de mes propres classes. J'ai également essayé de changer le point de pointe sur exécution (* org.ibernate.sesssfactory.opensession (..)) code>, mais sans résultat. P>

Je soupçonne que cela est causé Par comment je configurais hibernate, car je ne configure pas un SéanceFactory code> explicitement; J'ai plutôt mis en place un entitymanagerfactory code>. Voici ma configuration. P>

@Configuration
@ComponentScan(basePackages = { ... })
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {
    // ...
}


7 commentaires

Peut-être un @ComponentsCan ("org.hibernate") aide?


@Ruben Non, ça ne fait pas une différence.


Vous interceptez le SéanceFactory mais utilisez un JPA uni (avec hibernate comme implémentor). Cela ne va évidemment jamais lancer, il n'y a pas de SéanceFactory dans votre config et que votre aspect correspondra donc à rien. Écrivez le point coupé pour le entitymanagerfactory.getentitymanager à la place.


@ M.Deinum qui a du sens. Je l'ai essayé, mais je ne pouvais pas le faire travailler. Si j'ai @enableaspypjautoproxy (proxytargetclass = true) défini, je reçois l'exception suivante: java.lang.illegalargumentException: ne peut pas sous-classer la classe finale . Si je retire l'annotation, mon projet compile, mais le pointCut ne fonctionne pas. J'ai essayé divers points de pointe directement sur localContainerentityManagerFactorybean , mais jusqu'à présent pas de chance.


Et votre appconfig et persistenceConfig sont chargés dans le même contexte? AOP fonctionne uniquement pour les haricots définis dans le même contexte d'application.


Au meilleur de ma connaissance, oui. Voici mon web.xml et appconfig : Pastebin.com/df1rg0lu


Pourquoi avez-vous besoin proxytargetclass quand même? Vous ne devriez pas avoir besoin de cela. De plus, je suggérerais de supprimer AfterProgeresseSet () et getObject () à partir de votre classe de configuration et laissez la poignée de ressort qui.


3 Réponses :


1
votes

Peut-être que ce n'est que le fait que vous déclarez le pointCut à l'aide de l'interface org.hibernate.sessfactory comme argument d'exécution ...

@pointCut ("exécution (* org.hibernate.sesssfactory.getCurtionSession.gecurrentSession (..))")

La manière appropriée consiste à définir l'exécution de PointCut au fur et à mesure de la mise en œuvre de cette interface et de la notation pour cela n'est qu'un bit différent, voir le signe +

@pointCut ("Exécution (* org.hibernate.sessfactory + .getCurrentSession (..))")

Aussi une notation alternative ...

@pointcut ("dans (ORG.Hibernate.SessieFactory +) && Exécution (* getCurrentSession (..))")

Vous devez également consulter aspectj-triche-feuille < / a>

concernant java.lang.illegalargumentException: ne peut pas sous-classer la classe finale . La classe ciblée est la mise en œuvre concrète de org.ibernate.sessfactory nommément org.hibernate.internal.sessfactoryimpl qui se trouve être final, Séance de classe finale publique .

A proxyTargetClass = Vrai Configuration selon le documentation

Indiquez si les procurations sous-classes basées sur la sous-classe (CGLIB) doivent être créées, par opposition à des proxies de l'interface Java standard.

Mais puisque la classe que vous essayez de sous-classe est finale Il y a un peu de problème en fonction du Spécification de la langue Java

Il s'agit d'une erreur de compilation si le nom d'une classe finale apparaît dans la clause étendue (§8.1.4) d'une autre déclaration de classe; Cela implique qu'une classe finale ne peut avoir de sous-classes.


9 commentaires

Merci pour votre réponse! Malheureusement, j'ai essayé les points de pointe que vous avez mentionnés, mais ils ne travaillaient pas pour moi.


Avez-vous essayé d'utiliser un localentitymanagerfactorybean au lieu de localContainerentityManagerFactorybean ? Je ne suis pas un expert dans ce domaine, mais je sais que c'est le premier qui produit un entittityManagerFactoryFactoryFactory et non géré par le conteneur, qui est produit par ce dernier ... et nous voulons vraiment le printemps pour gérer cela afin que l'AOP travaux :)


Maintenant, je comprends que l'AOP est cool et tout cela, mais vous devriez vraiment jeter un coup d'œil aux solutions possibles suivantes impliquant également la gestion de la session: org.springframework.orm.hibernate4.support.opensessioninc eptor ou Org.hibernate.SessieventListener


Ou encore mieux, examinez cet article abondant à l'aide de SPI d'Hibernate Événement géré-Spring-Souditeurs-avec-JPA . Je parie que cela peut présenter une alternative beaucoup plus décente à cette inoption Contraction :)


Je pense que cela devrait se présenter comme une alternative également OpenSessionInviewFilter


J'ai examiné vos propositions. Hibernate's SPI semble être une bonne solution, mais j'ai pris un coup d'œil sur le types d'événements disponibles , et je n'ai pas pu trouver un approprié à utiliser. En théorie, je suppose que je pourrais utiliser l'événement init_collection , mais je ne veux pas activer un filtre à chaque fois appelé (potentiellement plusieurs fois). Des idées ici? Je ne pense pas que l'opensessionInviewFilter est applicable ici, car il étend simplement la durée de vie de la session à la durée de la demande.


Concernant OpenSessessInterceptor , comment avez-vous imaginé que cela puisse être utilisé? Je comprends comment l'intercepteur fonctionne, mais je ne suis pas sûr à 100% comment l'appliquer à mon cas d'utilisation. L'intercepteur lui-même ne me donne aucun contrôle de la session. J'imagine donc que je devrais utiliser un conseil et faire une pointe à cet intercepteur afin de manipuler la session? J'ai l'impression d'avoir presque compris avec le Aide de la documentation , mais je manque toujours des morceaux dans l'ordre Pour l'appliquer à mon projet. Toute aide ici serait très appréciée!


Pour Hibernate 4 Spring fournit un accès à 'ORG.Hibernate.SessFactory' par org.springframework.orm.hibernate4.localsesssFactoryBuilde r Et c'est un haricot géré à ressort et tout point de pointe AOP s'appliquera évidemment. Je ne sais tout simplement pas si c'est suffisamment polyvalent pour que vous obteniez exactement ce que vous recherchez


Désolé, il s'agit du haricot d'usine non aussi obsolète qui crée une usine de session hibernate ... org.springframework.orm.hibernate4.localsesssessorybean Vous pouvez alors gâcher avec



1
votes

Votre classe d'aspect semble bonne.

Ajouter @filter et @filterdef sur vos entités:

  • @filter: ajoute un filtre à une entité ou une entité cible.
  • @filterdef: Définit le nom de définition du filtre et les paramètres pour définir des valeurs tout en activant le filtre.

    Exemple: xxx

    dans votre configuration, le filtre est activé, mais n'a aucun paramètre.

    exemple à tester: < / p> xxx

    Bien sûr, vous pouvez définir autant de paramètres que nécessaire dans @Filterdef Annotation.

    En espérant que cela vous aide. Cordialement, Andrà ©.


1 commentaires

J'ai déjà déclaré le filtre dans mon entité, mais le problème est que le filtre n'est jamais activé à la session. Ceci est censé arriver à mon aspect, mais le filtre n'est jamais activé car ce code n'est pas exécuté. Mon filtre n'a pas besoin d'un paramètre, je n'ai donc pas ajouté aucun paramètre.



0
votes

faisait face à la question exacte. J'ai pu le résoudre en utilisant EntityManager et obtenir les informations de session à l'aide de sa méthode de débit plutôt que d'obtenir les informations de session à l'aide de Pointe Cut autour de l'appel GetCurrentSession de SéditionFactory.

@PersistenceContext
private EntityManager entityManager;

@Around("myPointcut")
public Object enableGlobalFilter(ProceedingJoinPoint pjp) throws Throwable {
            Session session = entityManager.unwrap(Session.class);
            Filter filter = session.enableFilter("Published_Entity");
            filter.setParameter("is_publishedParam", true);
            Object obj  = pjp.proceed();
            session.disableFilter("Published_Entity");
            return obj;
 }


0 commentaires