Java EE 6: Comment sélectionner une unité de persistance pour entitymanager à l'aide des informations de connexion

StackOverflow https://stackoverflow.com/questions/8400566

Question

Je dois sélectionner un EntityManager dans mon projet JavaEE6 (JBoss7) en fonction d'une session de connexion. Un utilisateur "Peter" se traduira par l'utilisation de la base de données dbPeter et un utilisateur "Paul" se traduira par l'utilisation de la base de données dbPaul.

La question est maintenant, comment puis-je produire un gestionnaire d'entités qui est automatiquement lié à la base de données / unité de persistance correspondante?

J'utilise CDI pour injecter EntityManager. Ma première étape est donc d'avoir un producteur pour EntityManager qui recherche les informations de connexion de la session et sélectionne la base de données. Alors, comment sélectionner le contexte de base de données / persistance dans ce prducer ?? Depuis Jboss7, je ne vois plus aucune entrée jndi pour l'unité de persistance, donc une recherche jndi ne peut pas être envisagée.

J'ai essayé d'utiliser

@Produces
public EntityManager produceEM() {
    EntityManagerFactory managerFactory = Persistence.createEntityManagerFactory( "dbPaul" );

    return managerFactory.createEntityManager();
}

mais cela échoue lors du déploiement avec

HHH000231: Échec de l'exportation du schéma: java.sql.SQLException: vous ne pouvez pas définir l'autocommit pendant une transaction gérée!

C'est ok parce que l'endroit où le em est injecté est principalement à l'intérieur d'une transaction. Quelqu'un a une idée?

Était-ce utile?

La solution

Tout d'abord, je serais réticent à créer un code générique à la volée. Je suppose que vous devriez le faire dans chaque création d'instance DAO (ou quel que soit l'objet EJB que vous utilisez pour accéder à votre base de données). Si tel est le cas, réfléchissez-y à deux fois: la création d'un EntityManagerFactory est très coûteuse et doit généralement être effectuée une fois dans le cycle de vie d'une application. Comme alternative, je créerais probablement différents DAO pour chaque unité de persistance, en transférant la responsabilité d'utiliser l'un ou l'autre vers une couche supérieure, afin que vous puissiez toujours compter sur le conteneur pour créer le EntityManagerFactory.

Cela étant dit, dans votre contexte et en supposant que la méthode produireEM () est dans un EJB et que vous utilisez la sécurité gérée par conteneur, vous pouvez injecter le EJBContext via:

@Resource
EJBContext ejbContext;

De là, vous pouvez obtenir le EntityManager et créer votre EntityManager en fonction de celui-ci.

Si l'une des hypothèses n'est pas valide, faites-le moi savoir et essaiera de mettre à jour ma réponse.

< EDITED:

@Stateless
public class EntityManagerService {

   @Resource
   EJBContext ejbContext;

   @Produces
   public EntityManager produceEM() {

   EntityManagerFactory managerFactory = Persistence.createEntityManagerFactory(ejbContext.getCallerPrincipal().getName());

   return managerFactory.createEntityManager();

   }
}

Vous pouvez également créer votre propre mappage entre les noms d'utilisateurs et les noms de base de données, ce qui est probablement une bonne idée si vous souhaitez un découplage entre ceux-ci.

Autres conseils

Ce n'est pas exactement une réponse à votre question, mais avez-vous envisagé la multi-location JPA?AFAIK Hibernate et EclipseLink le prennent en charge.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top