2010-03-25 8 views
26

Quelqu'un peut-il expliquer quelle est la différence entre:Quelle est la différence entre @Resource UserTransaction et EntityManager.getTransaction()

@Resource 
UserTransaction objUserTransaction; 

et

EntityManager.getTransaction(); 

Et aussi ce qui est transaction gérée par conteneur? et comment devrais-je le faire dans ma façade de session si je veux insérer trois rangées dans la table dans la transaction.

+1

Un bon article pour avoir une meilleure idée sur les transactions EJB, OMI, un must http://entjavastuff.blogspot.com/2011/02/ejb-transaction-management-going-deeper.html – thirdy

Répondre

26

EJB sont des composants transactionnels. La transaction peut être gérée soit par le serveur applicaiton lui-même (CMT - transaction gérée par conteneur), soit manuellement par vous-même dans l'EJB (BMT - transaction gérée par bean).

EJB prend en charge la transaction distribuée par la spécification JTA. La transaction distribuée est contrôlé en utilisant UserTransaction, qui possède des méthodes begin, commit, rollback. Avec CMT, le serveur d'applications démarre, valide et annule la transaction (selon le code transaction annotations) pour vous et vous n'êtes pas autorisé à interférer. Cela signifie que vous ne devez pas accéder au UserTransaction dans ce cas. Cependant, avec BMT, vous le faites manuellement et vous contrôlez la transaction vous-même en utilisant le UserTransaction.

Passons maintenant à la EntityManager. Une implémentation JPA peut être utilisée dans un serveur d'applications ou autonome. Si vous l'utilisez en mode autonome, vous devez utiliser EntityManage.getTransaction pour délimiter vous-même la transaction JDBC. S'il est utilisé dans un serveur d'applications, le EntityManager a coopéré de manière transparente avec le gestionnaire de transactions distribué JTA pour vous.

La plupart du temps, vous utilisez CMT avec @Required annotation sur l'EJB. Cela signifie que vous n'avez pas besoin d'accéder à UserTransaction ni EntityManager.getTransaction. L'application. le serveur démarre et valide la transaction, mais prend également soin de revenir en arrière si une exception est déclenchée. C'est ce que je recommanderais pour votre façade.

(Il existe d'autres subtilités, telles que PersistenceContextType ou l'inscription manuelle du gestionnaire d'entités dans une transaction distribuée avec EntityManager.joinTransaction, mais uniquement si vous utilisez les technologies de manière différente par défaut).

+3

Etes-vous sûr que 'EntityManager # getTransaction()' coopère avec la transaction distribuée JTA lors de l'exécution à l'intérieur d'un serveur d'applications? Je ne pense pas que ce soit le cas, je crois comprendre qu'il renvoie une transaction ressource-locale qui peut être utilisée pour conserver les données * en dehors de la transaction JTA en cours. –

+0

@Pascal Le 'EntityManager' coopère avec JTA donc vous ne devriez pas utiliser' EntityManager # getTransaction'. Selon le javadoc, 'EntityManager # getTransaction' renvoie' IllegalStateException' s'il est invoqué sur un EntityManager JTA. – ewernli

+2

En effet, 'getTransaction' renvoie une exception lorsqu'il est appelé sur un EntityManager JTA). En fait, l'exemple que j'avais à l'esprit (à partir de "Pro JPA 2") est d'obtenir une application gérée, ressource EM locale dans un bean Session - par exemple. pour la journalisation d'audit - et une transaction locale de ressources que vous pouvez commencer/valider autant de fois que vous le souhaitez en dehors de la transaction JTA. Mais je réalise que j'ai mal lu votre réponse, c'est différent de ce que vous avez écrit. Merci! –

7

UserTransaction fait référence à l'entité de transaction JTA. Vous ne pourrez l'utiliser que si un module JTA est disponible sur le serveur d'applications: par exemple, si vous déployez une application sur Tomcat (qui, par défaut, ne prend pas en charge JTA), le code basé sur cet élément échouera . C'est le type de transaction par défaut utilisé dans les EJB et les MDB. Récupère une entité de transaction locale. Ceci est aussi parfois connu comme une transaction locale de ressource.

ressources transactions locales sont très différentes de transactions JTA: entre autres, les transactions locales de ressources sont spécifiques à une ressource, alors que les transactions JTA ont tendance à être spécifiques à un fil particulier.

Pour plus d'informations sur la différence entre les ressources des transactions locales et JTA, voir cette Stackoverflow répondre ici: What is the difference between a JTA and a local transaction?

0

En plus de @ la réponse de Marco qui fait bien de dire la différence entre la JTA et de ressources transactions locales.

Les transactions gérées par conteneur [sont nommées] sont gérées par le conteneur plutôt que par votre application. Cela se fait via le niveau EJB où vous avez juste besoin d'écrire votre méthode et le conteneur entourera la méthode autour d'un contexte de transaction. Si une partie de votre méthode ou ses appels de niveau inférieur lève une exception, la transaction sera annulée.

Il peut également être affiné en utilisant des annotations. Plus d'informations peuvent être trouvées ici

Notez que ceci est fait uniquement par le biais des EJB, et les gestionnaires d'entités qui sont injectés sur le niveau Web (par exemple servlets ou API REST) ​​ne sont pas gérés par le conteneur, auquel cas vous devez recherchez la transaction en utilisant @Resource UserTransaction ou EntityManager.getTransaction, begin() et commit() vous-même. A partir de Java EE 6, vous avez la possibilité d'avoir des EJB dans le niveau Web. Vous n'avez donc pas besoin d'une mise en page de projet trop complexe à moins que vous ne souhaitiez exposer vos EJB en tant que services Web.

+0

Les transactions gérées par conteneur EE sont disponibles en dehors d'EJB via l'annotation "@Transactional". –

+0

Les transactions JTA ne sont pas nécessairement des CMT, car JTA peut être utilisé en dehors des serveurs d'applications (ou «containers») avec des bibliothèques telles que Bitronix et Atomikos. – Marco