Musimy być w stanie uzyskać skojarzenie java.sql.Connection
z sesją hibernacji. Żadne inne połączenie nie będzie działać, ponieważ to połączenie może być powiązane z uruchomioną transakcją.
Jeśli session.connection () jest teraz przestarzała, jak mam to zrobić?
Odpowiedzi:
Teraz musisz użyć Work API:
session.doWork( new Work() { public void execute(Connection connection) throws SQLException { doSomething(connection); } } );
Lub w Javie 8+:
źródło
SessionImpl sessionImpl = (SessionImpl) session; Connection conn = sessionImpl.connection();
Następnie możesz użyć obiektu connection wszędzie tam, gdzie potrzebujesz go w tym kodzie, a nie tylko ograniczając się do małej metody.session.doWork(this::doSomething)
. Jeśli chcesz zwrócić wynik - użyj doReturningWork ()Musisz użyć
Session#doWork(Work)
iWork
API, jak wspomniano w Javadoc:Masz trochę czasu przed Hibernate 4.x, ale cóż, używanie przestarzałego API wygląda jakoś tak:
:)
Aktualizacja: Według RE: [hibernate-dev] Połączenie proxy na liście hibernate-dev wydaje się, że początkowym zamiarem wycofania było zniechęcenie do używania,
Session#connection()
ponieważ był / jest uważany za „zły” interfejs API, ale miał w tym czasie zostać. Chyba zmienili zdanie ...źródło
Session#connection()
w Hibernate Core 3.3 wspomina o alternatywie) i zazwyczaj jest to coś, czego czytelnicy nie mogą odgadnąć.hibernate
), a niehibernate-core
który ma nowsze wersje. W przypadku ostatecznych wersji (3.5.x) są one dostępne w repozytorium JBoss Nexus .Spróbuj tego
W rzeczywistości getSession zwraca typ interfejsu sesji, powinieneś zobaczyć, jaka jest oryginalna klasa dla sesji, wpisz rzut do oryginalnej klasy, a następnie uzyskaj połączenie.
POWODZENIA!
źródło
SessionImpl
znajduje się w wewnętrznym pakiecie Hibernate (więc nie jest przeznaczony do użycia), a także jest zależny od rzeczywistej implementacji. Nie możesz też łatwo kpić z sesji w swoich testach, kiedy ją przesyłasz.Jest jeszcze jedna opcja, w której wciąż jest zaangażowanych wiele rzutów, ale przynajmniej nie wymaga ona refleksji, co pozwoli ci z powrotem sprawdzić czas kompilacji:
public Connection getConnection(final EntityManager em) { HibernateEntityManager hem = (HibernateEntityManager) em; SessionImplementor sim = (SessionImplementor) hem.getSession(); return sim.connection(); }
Możesz oczywiście uczynić to jeszcze „ładniejszym” kilkoma
instanceof
sprawdzeniami, ale powyższa wersja działa dla mnie.źródło
Oto sposób na zrobienie tego w Hibernate 4.3 i nie jest on przestarzały:
źródło
session
na format jest bezpiecznaSessionImplementor
?To jest to, czego używam i działa dla mnie. Przerzuć obiekt Session do SessionImpl i łatwo pobierz obiekt połączenia:
gdzie
session
jest nazwa obiektu sesji Hibernate.źródło
connection()
został właśnie wycofany w interfejsie. Nadal jest dostępny naSessionImpl
. Możesz zrobić to, co robi Spring i po prostu to nazwać.Oto kod z
HibernateJpaDialect
Spring 3.1.1public Connection getConnection() { try { if (connectionMethod == null) { // reflective lookup to bridge between Hibernate 3.x and 4.x connectionMethod = this.session.getClass().getMethod("connection"); } return (Connection) ReflectionUtils.invokeMethod(connectionMethod, this.session); } catch (NoSuchMethodException ex) { throw new IllegalStateException("Cannot find connection() method on Hibernate session", ex); } }
źródło
Znalazłem ten artykuł
package com.varasofttech.client; import java.sql.Connection; import java.sql.SQLException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.SessionImpl; import org.hibernate.jdbc.ReturningWork; import org.hibernate.jdbc.Work; import com.varasofttech.util.HibernateUtil; public class Application { public static void main(String[] args) { // Different ways to get the Connection object using Session SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); Session session = sessionFactory.openSession(); // Way1 - using doWork method session.doWork(new Work() { @Override public void execute(Connection connection) throws SQLException { // do your work using connection } }); // Way2 - using doReturningWork method Connection connection = session.doReturningWork(new ReturningWork<Connection>() { @Override public Connection execute(Connection conn) throws SQLException { return conn; } }); // Way3 - using Session Impl SessionImpl sessionImpl = (SessionImpl) session; connection = sessionImpl.connection(); // do your work using connection // Way4 - using connection provider SessionFactoryImplementor sessionFactoryImplementation = (SessionFactoryImplementor) session.getSessionFactory(); ConnectionProvider connectionProvider = sessionFactoryImplementation.getConnectionProvider(); try { connection = connectionProvider.getConnection(); // do your work using connection } catch (SQLException e) { e.printStackTrace(); } } }
Pomogło mi.
źródło
Przy
Hibernate
> = 5,0 można uzyskać takiConnection
efekt:źródło
W przypadku hibenate 4.3 spróbuj tego:
public static Connection getConnection() { EntityManager em = <code to create em>; Session ses = (Session) em.getDelegate(); SessionFactoryImpl sessionFactory = (SessionFactoryImpl) ses.getSessionFactory(); try{ connection = sessionFactory.getConnectionProvider().getConnection(); }catch(SQLException e){ ErrorMsgDialog.getInstance().setException(e); } return connection; }
źródło
Spróbuj tego:
public Connection getJavaSqlConnectionFromHibernateSession() { Session session = this.getSession(); SessionFactoryImplementor sessionFactoryImplementor = null; ConnectionProvider connectionProvider = null; java.sql.Connection connection = null; try { sessionFactoryImplementor = (SessionFactoryImplementor) session.getSessionFactory(); connectionProvider = (ConnectionProvider) sessionFactoryImplementor.getConnectionProvider().getConnection(); connection = connectionProvider.getConnection(); } catch (SQLException e) { e.printStackTrace(); } return connection; }
źródło
Connection conn = null; PreparedStatement preparedStatement = null; try { Session session = (org.hibernate.Session) em.getDelegate(); SessionFactoryImplementor sfi = (SessionFactoryImplementor) session.getSessionFactory(); ConnectionProvider cp = sfi.getConnectionProvider(); conn = cp.getConnection(); preparedStatement = conn.prepareStatement("Select id, name from Custumer"); ResultSet rs = preparedStatement.executeQuery(); while (rs.next()) { System.out.print(rs.getInt(1)); System.out.println(rs.getString(2)); } } catch (Exception e) { e.printStackTrace(); } finally { if (preparedStatement != null) { preparedStatement.close(); } if (conn != null) { conn.close(); } }
źródło
Oto metoda Java 8, która zwraca wartość
Connection
używaną przez program,EntityManager
nie robiąc jeszcze nic z tym:private Connection getConnection(EntityManager em) throws SQLException { AtomicReference<Connection> atomicReference = new AtomicReference<Connection>(); final Session session = em.unwrap(Session.class); session.doWork(connection -> atomicReference.set(connection)); return atomicReference.get(); }
źródło