Je travaille sur une application qui doit faire des opérations de base de données.
J'ai créé une variable statique pour EntityManagerFactory code> et l'initialisée dans la méthode qui est appelée par l'application p > if (emf == null) {
emf = Persistence.createEntityManagerFactory("example");
}
try {
em = emf.createEntityManager();
} catch (Exception ex) {
logger.error(ex.getMessage());
}
5 Réponses :
Vous devez mettre des verrous sur un objet lorsque vous créez le EMF code>. Vous peut em> mettre les serrures sur l'objet code> EMF code> lui-même, mais ce n'est pas la meilleure pratique. Créez un autre objet: lock(factoryLockObject) {
if (emf == null) {
emf = Persistence.createEntityManagerFactory("example");
}
}
Quelle différence cela fait-il? Je vais essayer.
Cela ajoutera un verrouillage d'objet sur l'obstacle FactoryLockObject et provoquera les autres threads souhaitant y accéder pour attendre jusqu'à ce que la serrure soit levée (à la dernière attelle bouclée). CSHARPINDEPTH.COM/Articles/General/singleton.aspx
Néanmoins, ne bloquera-t-il pas les threads? Si la persistance.createentityManagerFactory ("exemple"); Le fil est en sécurité, alors je n'ai pas besoin de le synchroniser.
Je ne sais pas si la persistance est le fil-à-plan interne. Le verrouillage que j'ai montré provoquera des threads souhaitant exécuter ce bloc de code à attendre jusqu'à ce que le premier thread soit terminé. C'est pourquoi votre si doit aller à l'intérieur du verrou.
Un moyen facile de "résoudre" ce serait d'utiliser une classe d'assistance (une classe et le "problème" est parti. P> p> hibernatetutil code>) et d'initialiser l'entitéanageriserfactory code> dans un bloc d'initialisation statique. Quelque chose comme ceci:
Je l'ai fait auparavant. Mais certaines personnes sentent que ce n'est pas une bonne pratique pour initialiser dans les blocs statiques. Est-ce correct?
@Vanchinathan C'est vraiment une approche typique lorsque vous n'êtes pas dans un environnement géré et que je ne vois rien de mal avec ça. Maintenant, si vous fournissez des arguments contre cela, nous pourrions en discuter mais jusqu'à présent, je maintiens cette recommandation.
L'un des arguments que je reçois toujours est que le code dans les blocs statiques, en empêche les tests. Nous suivons le développement axé sur le test strictement. J'ai donc besoin de quelque chose qui est également plus facile à tester.
@Vanchinathan toujours, vous souhaitez initialiser l'EMF une seule fois, c'est pourquoi le motif ci-dessus est utilisé. Vous devriez ensuite utiliser ce code pour obtenir un entitémanager et l'injecter dans les classes qui en ont besoin (et celles-ci seront bien testables).
La question était la suivante: CatégorieManager () Thread-Safe? La réponse après avoir examiné un code et la définition de la classe est qu'elle est "à l'échelle de l'application" dans la portée du thread-Safe. Les instances d'entitémanager ne sont cependant pas du thread-coffre-fort. Cela fonctionne donc bien que je recommandais un simple singleton modèle pour obtenir la poignée à l'usine. La raison en est que les blocs code> statiques code> sont considérés vers le chargeur de la classe de conteneur sur le moment où ils se chargent. Cela pourrait être avant le chargement du cadre de la persistance-manager.
Si Si vous attendez simplement qu'un autre thread de créer l'usine bloque votre application, que se passera-t-il lorsque chaque thread crée sa propre, encombrant le travail d'autres threads dans le processus? P>
Le code que vous affichez doit être à l'intérieur d'un bloc code> synchronisé code>, ou ce n'est pas le fil de sécurité. P> CreateTityManagerFactory () code> est le fil ou non, vous avez besoin d'une stratégie de manière à ce qu'elle soit invoquée une seule fois. En d'autres termes, cette question est hors de propos, car vous devez vous assurer qu'un seul thread l'appelle. P>
Il n'y a pas besoin d'une stratégie pour appeler l'usine une fois. Une recherche doit être faite dans tous les cas et un motif singleton garantira que la poignée de l'instance actuelle (une) est toujours renvoyée. Tous les threads d'appel obtiendront la même référence à la même usine. Il n'y a pas besoin de synchronisation et créera en outre un problème de performance en tant que threads qui se battent pour gagner le moniteur vient d'être renvoyé dans la seule manche d'usine unique.
@Darrellteague Comment un appelant détermine-t-il si une usine est partagée ou non et que cela devrait être fermé par cet appelant? Selon l'OP, l'initialisation de l'usine prend beaucoup de temps. Créer de multiples cas inutiles tout au long de la vie de la demande semble un problème de performance beaucoup plus important que toute affirmation pouvant survenir lors de l'instant qu'il prend pour simplement synchroniser et lire une variable, une fois initialisée.
J'utilise la persistance.createentityManagerFactory (ID) comme une instance statique, singulière et c'est le fil-coffre-fort. Ce qui doit être gardé sur la sécurité, ce sont les instances d'EntityManager de EMF.CreateentityManager (). Qui doit être à l'intérieur d'une méthode donnée, suivi de la création d'une transaction, de la valider puis de l'appeler près () sur l'entitémanager (qui est identique à la connexion J2EE DataSource.close () pour libérer la connexion JDBC à la piscine-Manager ). C'est le même modèle que Pre-JPA avec connexion DataSource et JDBC via un gestionnaire de pool.
Je ne vois aucune question avec l'approche de bloc statique. Ou vous pouvez faire la même chose de la manière ci-dessous qui est un motif singleton avec vérification de double verrouillage et vous appellerez p> EntityManager myManager = JPAhelper.getInstance().getJPAFactory().createEntityManager();
Le motif singleton est recommandé mais il n'y a pas besoin (ou effet) d'utiliser un verrou à double vérification. CreateTyTyManagerFactory () est déjà le thread-coffre-fort et retournera la même poignée à la même usine dans tous les cas. Un singleton correctement écrit qui chargea l'usine statiquement renvoyera toujours la poignée. Les serrures à double vérification ne fonctionnent pas dans des conteneurs / systèmes d'application réels. Voir ceci: http://www.cs.umd.edu/ ~ Pugh / Java / MemoryModel / DoubleCheckedlo cking.html
Double-vérifie les serrures fonctionnent dans des applications réelles. Le code ci-dessus devrait déclarer MyFactory comme volatile. Le même article référencé explique "la fixation de verrouillage à double vérification à l'aide de volatiles"
La réponse à la question est la suivante: Oui, CreateTyTyManagerFactory () est sur la coffre-fort sur la documentation de la classe, la source et les résultats de l'application du monde réel. P>
La réponse du modèle Singleton est la plus correcte pour éviter un appel supplémentaire pour récupérer efficacement la poignée d'usine d'une usine, mais rien ne nécessite qu'un verrou de double contrôle comme commenté précédemment. P>