session.connection() объявлен устаревшим в Hibernate?
Нам нужно иметь возможность получить связанные java.sql.Connection
зимней сессии. Никакое другое соединение не будет работать, так как это соединение может быть связано с выполняющейся транзакцией.
Если метод session.connection() устарел, как я могу это сделать?
14 ответов
Теперь вы должны использовать Work API:
session.doWork(
new Work() {
public void execute(Connection connection) throws SQLException
{
doSomething(connection);
}
}
);
Или в Java 8:
session.doWork(connection -> doSomething(connection));
Если
session.connect()
сейчас не рекомендуется, как я должен это сделать?
Вы должны использовать Session#doWork(Work)
и Work
API, как упомянуто в Javadoc:
connection()
Устаревшее. (планируется удалить в 4.x). Замена зависит от необходимости; за прямое использование JDBCdoWork(org.hibernate.jdbc.Work)
; для использования "временного сеанса" (TBD).
У вас есть некоторое время до Hibernate 4.x, но использование устаревшего API выглядит следующим образом:
:)
Обновление: в соответствии с RE: [hibernate-dev] прокси-сервер Соединения в списке hibernate-dev, кажется, что первоначальное намерение устареть было препятствовать использованию Session#connection()
потому что он был / считается "плохим" API, но должен был остаться в то время. Я думаю, они изменили свое мнение...
Попробуй это
((SessionImpl)getSession()).connection()
На самом деле getSession возвращает тип интерфейса сеанса, вы должны увидеть исходный класс для сеанса, набрать тип в исходном классе и получить соединение.
УДАЧИ!
Это то, что я использую и работает для меня. Загрузите метод Session в SessionImpl и легко получите объект подключения:
SessionImpl sessionImpl = (SessionImpl) session;
Connection conn = sessionImpl.connection();
где session
имя вашего объекта сеанса Hibernate.
Вот способ сделать это в Hibernate 4.3, и это не рекомендуется:
Session session = entityManager.unwrap(Session.class);
SessionImplementor sessionImplementor = (SessionImplementor) session;
Connection conn = sessionImplementor.getJdbcConnectionAccess().obtainConnection();
Есть еще один вариант с большим количеством приведений, но по крайней мере он не нуждается в рефлексии, который вернет вам проверку времени компиляции:
public Connection getConnection(final EntityManager em) {
HibernateEntityManager hem = (HibernateEntityManager) em;
SessionImplementor sim = (SessionImplementor) hem.getSession();
return sim.connection();
}
Конечно, вы можете сделать это еще "красивее" с помощью нескольких instanceof
проверяет, но версия выше у меня работает.
Я нашел эту статью
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();
}
}
}
Это помогло мне.
connection()
просто устарела на интерфейсе. Это все еще доступно на SessionImpl
, Вы можете сделать то, что делает Spring, и просто назвать это.
Вот код из HibernateJpaDialect
весной 3.1.1
public 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);
}
}
С Hibernate
>= 5.0 вы можете получить Connection
как это:
Connection c = sessionFactory.
getSessionFactoryOptions().getServiceRegistry().
getService(ConnectionProvider.class).getConnection();
Для hibenate 4.3 попробуйте это:
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;
}
Попробуй это:
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;
}
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();
}
}
Если вам нужно возвращаемое значение изнутри лямбды, не упускайте из видуdoReturningWork()
try {
return session.doReturningWork(connection -> {
try (CallableStatement cs = connection.prepareCall(...)) {
cs.doSomethingPseudoMethod();
cs.executeUpdate();
return cs;
}
});
} catch (SQLException sqlException) {
...
}
Вот метод Java 8 для возврата Connection
используется EntityManager
фактически ничего не делая с ним:
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();
}