How to get DataSource or Connection from JPA2 Enti

2020-02-10 15:51发布

问题:

I have a working application where I use Java EE 6 with EclipseLink for persistence and a PostgreSQL database.

For the User-Registration I want to set the password in PostgreSQL to:

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

As I cant use DigestUtils for this, I have to insert the user manually into the DB. To keep my application configurable I do not want to query the DataSource with an InitialContextInstance.lookup(dataSource) but to extract it (or the Connection) somehow from the EntityManager like:

DataSource ds = entityManagerInstance.someFunctionThatReturnsADataSourceOrConnection();

Or would it be possible to use createNativeQuery or something similar in conjuntion with a prepared statement to protect against injections?

回答1:

sometimes it just takes another run in google:

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

as described in the Eclipse Link Documentation



回答2:

In response to "Archimedes Trajano" comment to the accepted answer, does the accepted answer work for other than Eclipselink? The answer is no for at least Hibernate.

I got the following error when I tried the accepted answer for hibernate:

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]

A combination of answers from the following stackoverflow questions allowed me to come up with a solution that works for Hibernate.

Get hold of a JDBC Connection object from a Stateless Bean

Hibernate get Connection object for JasperRunManager

Here is my 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
        }
    });


回答3:

Here is a snippet of code that works with Hibernate 4, based on dulon's answer

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;
    }

}