Как получить источник данных или соединение из JPA2 EntityManager в Java EE 6
У меня есть работающее приложение, где я использую Java EE 6 с EclipseLink для персистентности и базу данных PostgreSQL.
Для регистрации пользователя я хочу установить пароль в PostgreSQL для:
... password = crypt('inputPassword',gen_salt('bf')) ...
Поскольку я не могу использовать DigestUtils для этого, я должен вручную вставить пользователя в БД. Чтобы сохранить конфигурируемость моего приложения, я не хочу запрашивать источник данных с помощьюInitialContextInstance.lookup(dataSource)
но чтобы извлечь его (или Соединение) как-то из EntityManager, например:
DataSource ds = entityManagerInstance.someFunctionThatReturnsADataSourceOrConnection();
Или было бы возможно использовать createNativeQuery или что-то подобное в сочетании с подготовленным оператором для защиты от инъекций?
3 ответа
Иногда это просто повторяется в Google:
entityManager.getTransaction().begin();
java.sql.Connection connection = entityManager.unwrap(java.sql.Connection.class);
...
entityManager.getTransaction().commit();
как описано в документации по Eclipse Link
В ответ на комментарий Архимеда Траяно к принятому ответу, работает ли принятый ответ не для Eclipselink? Ответ - нет, по крайней мере, 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]
Комбинация ответов из следующих вопросов об стеке потока позволила мне найти решение, которое работает для Hibernate.
Получить объект JDBC-соединения из компонента без состояния
Hibernate получить объект подключения для 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
}
});
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;
}
}