web-dev-qa-db-fra.com

Comment obtenir DataSource ou une connexion à partir de JPA2 EntityManager dans Java EE 6

J'ai une application de travail où j'utilise Java EE 6 avec EclipseLink pour la persistance et une base de données PostgreSQL.

Pour l'enregistrement d'utilisateur, je veux définir le mot de passe dans PostgreSQL pour:

... password = crypt('inputPassword',gen_salt('bf')) ...

Comme je ne peux pas utiliser DigestUtils pour cela, je dois insérer l'utilisateur manuellement dans la base de données. Pour que mon application reste configurable, je ne souhaite pas interroger le DataSource avec un InitialContextInstance.lookup(dataSource) mais l'extraire ( ou la connexion) en quelque sorte de EntityManager comme:

DataSource ds = entityManagerInstance.someFunctionThatReturnsADataSourceOrConnection();

Ou serait-il possible d'utiliser createNativeQuery ou quelque chose de similaire en conjonction Avec une déclaration préparée pour se protéger contre les injections?

11
zuloo

parfois, il faut juste une autre course dans google:

entityManager.getTransaction().begin();
Java.sql.Connection connection = entityManager.unwrap(Java.sql.Connection.class);
...
entityManager.getTransaction().commit();

comme décrit dans Eclipse Link Documentation

15
zuloo

En réponse au commentaire "Archimedes Trajano" sur la réponse acceptée, la réponse acceptée fonctionne-t-elle pour autre chose qu'Eclipselink? La réponse est non pour au moins Hibernate.

J'ai eu l'erreur suivante lorsque j'ai essayé la réponse acceptée pour mettre en veille prolongée:

Caused by: org.springframework.orm.jpa.JpaSystemException: Hibernate cannot unwrap interface Java.sql.Connection; nested exception is javax.persistence.PersistenceException: Hibernate cannot unwrap interface Java.sql.Connection
     at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.Java:418) ~[spring-orm-4.0.5.RELEASE.jar:4.0.5.RELEASE]

Une combinaison de réponses aux questions de stackoverflow suivantes m'a permis de proposer une solution qui fonctionne pour Hibernate.

Obtenez un objet de connexion JDBC à partir d'un bean sans état

Objet Hibernate get Connection pour JasperRunManager

Voici ma solution:

    Session hibernateSession = entityManager.unwrap(Session.class);

    hibernateSession.doWork(new org.hibernate.jdbc.Work() {

        @Override
        public void execute(Connection connection) throws SQLException {
            // do whatever you need to do with the connection
        }
    });
5
dulon

Voici un extrait de code qui fonctionne avec Hibernate 4, basé sur la réponse de dulon

Connection getConnection() {
        Session session = entityManager.unwrap(Session.class);
        MyWork myWork = new MyWork();
        session.doWork(myWork);
        return myWork.getConnection();
}


private static class MyWork implements Work {

    Connection conn;

    @Override
    public void execute(Connection arg0) throws SQLException {
        this.conn = arg0;
    }

    Connection getConnection() {
        return conn;
    }

}
0
uvperez