Как получить DataSource или соединение из JPA2 EntityManager в Java EE 6

У меня есть рабочее приложение, в котором я использую Java EE 6 с EclipseLink для сохранения и базы данных PostgreSQL.

Для регистрации пользователя Я хочу установить пароль в PostgreSQL для:

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

Поскольку я не могу использовать DigestUtils для этого, я должен вручную вставить пользователя в БД. Чтобы мое приложение настраивалось, я не хочу запрашивать DataSource с помощью InitialContextInstance.lookup(dataSource), но извлечь его (или соединение) каким-то образом из EntityManager как:

DataSource ds = entityManagerInstance.someFunctionThatReturnsADataSourceOrConnection();

Или можно было бы использовать createNativeQuery или что-то подобное в конъюнкции с подготовленным выражением для защиты от инъекций?

Ответ 1

иногда просто требуется другой запуск в google:

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

как описано в Документации по ссылкам Eclipse

Ответ 2

В ответ на комментарий "Архимед Трахано" к принятому ответу, работает ли принятый ответ за исключением Eclipselink? Ответ - нет, по крайней мере, для спящего режима.

У меня возникла следующая ошибка, когда я попробовал принятый ответ для спящего режима:

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]

Комбинация ответов из следующих вопросов stackoverflow позволила мне придумать решение, которое работает для Hibernate.

Получить объект соединения JDBC из безстоящего Bean

Hibernate получить объект Connection для JasperRunManager

Вот мое решение:

    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

Вот фрагмент кода, который работает с Hibernate 4, на основе ответа 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;
    }

}