Spring JPA : géré par l'Application de contexte de persistance avec @Transactionnelle et @PersistenceContext
Actuellement, im essayant de la géré par l'application de contexte de persistance, par la création de l'entité gestionnaire manuellement et de les stocker afin de permettre des transactions qui s'étend sur plusieurs demande d'appels (peut-être quelque chose comme contexte de persistance étendue) dans la JSE application.
Mais, im me demandais si je peux éviter l'envoi de l'objet entityManager tout au long du service et des méthodes DAO comme un paramètre supplémentaire en faisant usage du ressort de l' @PersistenceContext d'injection et de marquer les méthodes avec @Transactional annotation à utiliser le début de la transaction manuellement avec l'entité gestionnaire.
Je pense que je peux en quelque sorte gérer cela en utilisant un ThreadLocal pour cette fonction, mais je vais être plus heureux d'être en mesure de joindre le présent pour le framework spring.
Ceci est un exemple de Ce que j'ai à l'esprit :
L'INTERFACE utilisateur de la méthode d'action :
Ici, nous pouvons voir l'opération est lancée par la logique de l'interface utilisateur, puisqu'il n'y iss sans façade /méthode de commande dans le backend de groupe de ces appels à la logique d'entreprise :
Long transactionid = tool.beginTransaction();
//calling business methods
tool.callBusinessLogic("purchase", "receiveGoods",
paramObject1, transactionid);
tool.callBusinessLogic("inventory", "updateInventory",
paramObject2, transactionid);
tool.commitTransaction(transactionid);
À l'intérieur de l'outil :
public Long beginTransaction() {
//create the entity --> for the @PersistentContext
Entitymanager entityManager = createEntityManagerFromFactory();
long id = System.currentTimeMillis();
entityManagerMap.put(id, entitymanager);
//start the transaction --> for the @Transactional ?
entityManager.getTransaction().begin();
return id;
}
public void commitTransaction(Long transactionId) {
EntityManager entityManager = entityManagerMap.get(transactionId);
entityManager.getTransaction().commit();
}
public Object callBusinessLogic(String module, String function,
Object paramObject, Long transactionid) {
EntityManager em = entityManagerMap.get(transactionId);
//=================================
// HOW TO DO THIS????
//=================================
putEntityManagerIntoCurrentPersistenceContext(em);
return executeBusinessLogic(module, function, paramObject, transactionid);
}
Et l'exemple de la méthode de service :
public class Inventory {
//How can i get the entityManager that's been created by the tool for this thread ?
@PersistenceContext
private EntityManager entityManager;
//How can i use the transaction with that transactionId ?
@Transactional
public void receiveGoods(Param param) {
//........
}
}
Est-il de toute façon pour y parvenir ?
Merci !
Vous devez vous connecter pour publier un commentaire.
Printemps de la gestion de la
@PersistenceContext
annotation n' presque exactement ce que vous êtes après, avec une grande différence: vous obtenez toujours une opération étendue de l'EntityManager et le Printemps injecte toujours la même instance pour le même fil, de sorte que vous avez le genre de la propagation et de ne pas avoir à vous soucier de thread de sécurité. Mais vous ne serez jamais obtenir une extension de contexte cette manière!Croyez-moi, le Printemps 3 et étendu contexte de persistance n'est pas de bien jouer ensemble, peut-être que cela va changer au Printemps 3.1 mais je crains que ce n'est pas dans leur orientation. Si vous souhaitez utiliser un contexte de persistance étendue laissez Printemps injecter de l'EntityManagerFactory (via
@PersistenceUnit
annotation), puis de créer un EntityManager sur votre propre. Pour la multiplication, vous aurez à passer de l'instance comme un paramètre ou la stocker dans un ThreadLocal vous-même.@PersistenceContext
. Dois-je obtenir une autre entité gestionnaire de l'objet à chaque fois que j'appelentityManagerFactory.createEntityManager()
ou tout simplement partagé gestionnaire d'entité qui est injectée à l'aide de la@PersistenceContext
entityManagerFactory.createEntityManager()
crée un nouveau application-géré tout@PersistenceContext
injecte un container-managed instance. De vérifier la JPA spec pour la différence. Dans le cas spécifique du framework Spring le conteneur géré par l'instance de la transaction dont l'étendue et est lié à un thread local de sorte que chaque thread a au plus une seule instance à la fois. (il n'est pas nécessaire pour la synchronisation)En effet d'avoir une gérées par l'application de contexte de persistance, vous devez en quelque sorte de "pirater" le @Transactional & @PersistenceContext infrastructure en leur fournissant votre propre Gestionnaire d'Entité et ne laissez pas le Printemps de la création de ses propres.
La clé pour y parvenir est de jouer un peu avec les TransactionSynchronizationManager classe pour enregistrer votre propre Gestionnaire d'Entité à la thread local, le Printemps sera utiliser pour injecter de la @PersistenceContext attribut.
J'ai eu ce besoin il y a quelques temps pour mon application et j'ai conçu une petite architecture basée sur Spring AOP pour gérer le contexte de persistance étendue.
Plus de détails ici: JPA/Hibernate Global Conversation avec Spring AOP
Lorsque vous configurez vos transactions via @Transactional, alors vous devriez transfert de la configuration de vos transactions à l'annotation.
Ici vous démarrez votre transaction puis l'espoir que le @Transactionnelle sera également triggerd.
pour plus d'informations, vous feriez mieux de commencer la lecture de http://static.springsource.org/spring/docs/2.5.x/reference/transaction.html => 9.5.6. À L'Aide De @Transactional