Printemps @Transactional en lecture seule de propagation de l'
Je suis en train d'expérimenter en utilisant le modèle de commande pour permettre à mon calque web pour travailler avec les entités Hibernate dans le cadre d'une seule opération (évitant ainsi le chargement différé des exceptions). Cependant, je suis confus pour l'instant avec la façon dont je dois traiter les transactions.
Mes commandes d'appel de la couche de service méthodes annotées avec @Transactional
annotations. Certains de ces couche de service méthodes sont en lecture seule, par exemple @Transactional(readOnly=true)
- et certains sont en lecture/écriture.
Ma couche de service expose un gestionnaire de commande qui exécute les commandes passées sur le nom de la couche web.
@Transactional
public Command handle( Command cmd ) throws CommandException
Je suppose que je suis en droit de faire la commande du maître handle()
méthode transactionnelle. C'est là que la confusion vient dans. Si la mise en œuvre d'une commande permet d'appeler plusieurs couche de service méthodes, il n'y a aucun moyen pour le gestionnaire de commande pour savoir si les opérations dites au sein de la commande sera en lecture seule, lecture/écriture, ou une combinaison des deux.
Je ne comprends pas comment la propagation des œuvres dans cet exemple. Si je devais faire la handle()
méthode readOnly=true
, puis ce qui se passe si la commande appelle ensuite une couche de service méthode annotée avec @Transactional(realOnly=false)
?
J'apprécierais une meilleure compréhension de ce et vos commentaires sont les bienvenus...
Andrew
- Alors laquelle des deux réponses contradictoires est vrai? Quelqu'un a pris la peine de vérifier?
- Depuis
handle()
peut appeler des méthodes qui écrivent, l'opération doit permettre à l'écrit. Ce serait bien & bonne solution. Si vraiment vous vouliez, vous pourriez enquêter sur le démarrage de la TX par programmation & commutation en lecture seule, peut-être par le biais d'un attribut de Commande, mais je doute sérieusement que cela en vaut la peine.
Vous devez vous connecter pour publier un commentaire.
Tout d'abord, depuis le Printemps ne fait pas de la persistance de lui-même, il ne peut pas spécifier ce que
readOnly
devrait dire exactement. Cet attribut n'est qu'une indication pour le fournisseur, le comportement dépend, dans ce cas, Hibernate.Si vous spécifiez
readOnly
commetrue
, le flush mode sera défini commeFlushMode.NEVER
dans le courant de la Session Hibernate prévention de la session à partir de la validation de la transaction.En outre, setReadOnly(true) sera appelée sur la Connexion JDBC, qui est aussi un indice de la base de données. Si votre base de données prend en charge (la plus probable, il n'), ce qui a fondamentalement le même effet que
FlushMode.NEVER
, mais c'est plus fort puisque vous ne pouvez même pas rincer manuellement.Maintenant, nous allons voir comment la transaction propagation des œuvres.
Si vous n'avez pas explicitement défini
readOnly
àtrue
, vous aurez de la lecture/écriture des transactions. Selon les attributs de transaction (commeREQUIRES_NEW
), parfois, votre transaction est suspendue à un certain point, un nouveau est commencé et finalement engagé, et après que la première opération est la reprise.OK, nous y sommes presque. Voyons ce qu'apporte
readOnly
dans ce scénario.Si une méthode dans un de lecture/écriture transaction appelle une méthode qui nécessite un readOnly transaction, le premier devrait être suspendu, parce que sinon, une chasse d'eau/commettre arriverait-il à la fin de la seconde méthode.
À l'inverse, si vous appelez une méthode de dans un readOnly transaction qui nécessite de lecture/écriture, encore une fois, la première sera suspendu, car il ne peut pas être vidées/commis, et la deuxième méthode de besoins.
Dans le readOnly-à-readOnly, et la en lecture/écriture à lire/écrire cas la transaction externe n'a pas besoin d'être suspendu (sauf si vous spécifiez la propagation sinon, bien évidemment).
REQUIRES_NEW
, mais ce n'est pas la bonne solution pour la plupart des scénarios).Appel readOnly=false de readOnly=true ne fonctionne pas depuis la précédente opération continue.
Dans votre exemple, la méthode handle() sur votre couche de service est de commencer une nouvelle lecture-écriture de la transaction. Si la poignée de la méthode à son tour de service d'appels de méthodes annotées en lecture seule, il n'aura pas d'effet comme ils participeront à la lecture-écriture de la transaction à la place.
Si il est essentiel pour ces méthodes pour être en lecture seule, vous pouvez ensuite les annoter avec la Multiplication.REQUIRES_NEW, et ils vont commencer une nouvelle lecture seule transaction plutôt que de participer à la lecture-écriture de la transaction.
Ici est un exemple, CircuitStateRepository est une source de données JPA référentiel.
Haricots appels transactionnelle=lecture seule Bean1, qui fait une recherche et des appels transactionnelle=lecture-écriture Bean2 qui enregistre un nouvel objet.
31 09:39:44.199 [pool-1-thread-1] DEBUG o.s.orm.jpa.JpaTransactionManager - la Création de nouvelles transactions avec nom [nz.co.vodafone.wcim.d'affaires.Bean1.startSomething]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; "
Bean 2 pariticipates en elle.
Rien n'est déterminé à la base de données.
Maintenant changer Bean2
@Transactional
annotation pour ajouterpropagation=Propagation.REQUIRES_NEW
Bean1 commence une lecture seule tx.
Bean2 commence une nouvelle lecture-écriture tx
Et les modifications apportées par Bean2 sont désormais engagés dans la base de données.
Voici l'exemple, testé avec ressort de données, hibernate et oracle.
Par défaut transaction propagation est NÉCESSAIRE, ce qui signifie que la même opération va se propager à partir de la transaction appelant à transactionnelle destinataire de l'appel. Dans ce cas aussi la lecture-seule statut de propagation. E. g. si une lecture seule transaction appel de lecture-écriture de l'opération, l'ensemble de la transaction sera en lecture seule.
Pourriez-vous utiliser l'ouverture de Session dans une Vue de modèle pour permettre le chargement paresseux? De cette façon, votre poignée de méthode n'a pas besoin d'être transactionnelle à tous.
Il semble ignorer les paramètres de la transaction active, c'est seulement d'appliquer les paramètres d'une nouvelle transaction: