Получите объект соединения JDBC из компонента без состояния - PullRequest
12 голосов
/ 15 июля 2011

В компоненте сеанса без состояния вводится EntityManager, но я хотел бы получить объект Connection для вызова процедуры DB.Есть ли какое-то решение для этого?

Ответы [ 7 ]

16 голосов
/ 15 июля 2011

Это будет специфический код JPA-провайдера. Обычно это делается путем вызова unwrap() в классе EntityManager.

Если вы используете EclipseLink, будет полезен следующий код (из EclipseLink wiki ) (в случае, если вы используете EntityManager, управляемый приложением):

JPA 2,0

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

JPA 1,0

entityManager.getTransaction().begin();
UnitOfWork unitOfWork = (UnitOfWork)((JpaEntityManager)entityManager.getDelegate()).getActiveSession();
unitOfWork.beginEarlyTransaction();
Accessor accessor = unitOfWork.getAccessor();
accessor.incrementCallCount(unitOfWork.getParent());
accessor.decrementCallCount();
java.sql.Connection connection = accessor.getConnection();
...
entityManager.getTransaction().commit();

Обратите внимание, что решение, предусмотренное для JPA 2.0, не будет работать для Hibernate 3.6.5 с PersistenceException, содержащим сообщение

Hibernate не может развернуть интерфейс java.sql.Connection

Используйте код, предоставленный Skaffman, чтобы заставить его работать против Hibernate (проверено на работу под 3.6.5 даже для контекстов персистентности, управляемой контейнером).

Тем не менее, вики EclipseLink указывает на один полезный бит информации - если вы используете управляемые источники данных JTA, вы должны внедрить его с помощью аннотации @Resource или получить его с помощью поиска JNDI. Пока вам необходимо выполнить транзакционную работу с базой данных, не имеет значения, получаете ли вы новое соединение из источника данных или существующее; в любом случае большинство пулов соединений будет обеспечивать такое же соединение, которое связано с текущим потоком (то есть, тем, которое уже используется менеджером сущностей). Поэтому вы бы избегали развертывания менеджера сущностей таким способом, а также выполняли бы транзакционную деятельность с базой данных; помните, что кеш контекстного хранения и кэш второго уровня могут не синхронизироваться, если вы сделаете это.

9 голосов
/ 05 сентября 2014

В Hibernate решение, опубликованное skaffman, привело к следующему сообщению об ошибке:

Hibernate не может развернуть класс org.hsqldb.Session

Я получил егоработа с использованием SessionImpl вместо Session:

Connection connection = entityManager().unwrap(SessionImpl.class).connection();

Пример решения проблемы с использованием Session.doWork () следующий:

private void executeNative(final String query) {
    Session session = entityManager.unwrap(Session.class);
    session.doWork(new Work() {

        @Override
        public void execute(Connection connection) throws SQLException {
            Statement s = null;
            try {
                s = connection.createStatement();
                s.executeUpdate(query);
            } 
            finally {
                if (s != null) {
                    s.close();
                }
            }
        }

    });
}
7 голосов
/ 15 июля 2011

Кажется, что сам JPA API не предлагает этого, что неудивительно, но если вы хотите связать свой код с конкретной реализацией, вы можете использовать что-то вроде этого (Hibernate):

Session hibernateSession = entityManager.unwrap(Session.class);
Connection jdbcConnection = hibernateSession.connection(); 

Обратите внимание, что Session.connection() не рекомендуется для удаления в Hibernate 4. Попробуйте вместо этого использовать Session.doWork().

2 голосов
/ 15 июля 2011

Вы должны взять базовый делегат, используя entitymanager.getDelegate() или entitymanager.unwrap (что лучше), привести его к конкретной реализации (в Hibernate он называется Session). Затем вы можете вызвать метод connection(). Имейте в виду, что это устарело, используйте класс Work. Подробнее здесь .

1 голос
/ 07 марта 2016

В JPA2.0, если необходимо, JDBC является номинантом DTO или объектом для более сложного запроса.Иногда JPA не все ...

Я надеюсь, это поможет вам:

Statement statement = null;
EntityManager em = null;
em = emf.createEntityManager();
EntityTransaction et = em.getTransaction();

if(!et.isActive()) {
    et.begin();
}

java.sql.Connection connection = em.unwrap(java.sql.Connection.class);

    String qquerry="SELE ...
    try {   
        statement = connection.createStatement();
        ResultSet rs =  statement.executeQuery(qquerry);                                                              

        if (!rs.next()) {
            return null;
        }
        else{
            wwwwas=rs.getString(4);                                 
        }         
        statement.close();
        } 
    catch (SQLException e) {
        System.out.println("\n b-03:"+e);
        throw new RuntimeException(e.getMessage(), e);
    } 
    finally {
        try {
            //  em.getTransaction().commit();
            if(connection != null )
            connection.close();
        } 
        catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
       }
    }
1 голос
/ 17 мая 2015

Это работает потрясающе, и вы можете использовать объект подключения в другом месте, если это необходимо.

SessionImpl sessionImpl = (SessionImpl) session;
Connection conn = sessionImpl.connection();

Где session - имя объекта Hibernate Session

0 голосов
/ 24 февраля 2016

Ниже приведен код, который работал для меня. Мы используем jpa 1.0, реализацию Apache openjpa.

import java.sql.Connection;
import org.apache.openjpa.persistence.OpenJPAEntityManager;
import org.apache.openjpa.persistence.OpenJPAPersistence;



public final class MsSqlDaoFactory {


   public static final Connection getConnection(final EntityManager entityManager) {
          OpenJPAEntityManager openJPAEntityManager = OpenJPAPersistence.cast(entityManager);
          Connection connection = (Connection) openJPAEntityManager.getConnection();
          return connection;

    }

}
...