session.connection () không được dùng nữa trên Hibernate?


80

Chúng tôi cần có được liên kết java.sql.Connectioncủa một phiên ngủ đông. Không có kết nối nào khác sẽ hoạt động, vì kết nối này có thể được liên kết với một giao dịch đang chạy.

Nếu session.connection () hiện không được dùng nữa, tôi phải làm thế nào để làm điều đó?


Trong trường hợp có ai muốn đọc thêm về điều này: hibernate.onjira.com/browse/HHH-2603
WW.

9
Một trong nhiều lý do để tránh xa khuôn khổ khủng khiếp được gọi là Hibernate này. Đã đến lúc nó sẽ đi vào giấc ngủ vĩnh viễn như cái tên của nó.
chrisapotek

2
@chrisapotek Bạn không thích Hibernate ... bạn có lựa chọn thay thế nào không hay bạn viết tất cả những thứ liên tục bằng tay?
Emaborsa

1
Làm thế nào về mybatis?
Geoffrey Ritchey

Câu trả lời:


86

Bây giờ bạn phải sử dụng API Công việc:

session.doWork(
    new Work() {
        public void execute(Connection connection) throws SQLException 
        { 
            doSomething(connection); 
        }
    }
);

Hoặc, trong Java 8+:

session.doWork(connection -> doSomething(connection)); 

1
Tôi không thích sử dụng những thứ không dùng nữa nhưng tôi đoán đây là lý do chính đáng để bắt đầu sử dụng nó. Nhưng tôi không biết về API công việc. Cảm ơn rất nhiều.
TraderJoeChi Chicago

1
Chà. Tôi đang sử dụng Hibernate 3.2.7.ga nhưng org.hibernate.Session của tôi KHÔNG có bất kỳ phương thức doWork nào. Thật tuyệt!
TraderJoeChi Chicago,

25
Yuck thật là xấu xí. Mọi người luôn cần kết nối thô cho một thứ gì đó - họ nên làm cho nó dễ dàng.
Peter

9
SessionImpl sessionImpl = (SessionImpl) session; Connection conn = sessionImpl.connection();Sau đó, bạn có thể sử dụng đối tượng kết nối bất cứ nơi nào bạn cần trong mã đó không chỉ giới hạn trong một phương thức nhỏ.
Simon Mbatia

2
Thậm chí còn ngắn hơn trong Java8 - session.doWork(this::doSomething). Nếu bạn muốn trả về một kết quả - hãy sử dụng doReturningWork ()
Optio

22

Nếu session.connect()bây giờ không được dùng nữa, tôi phải làm như thế nào?

Bạn phải sử dụng Session#doWork(Work)WorkAPI, như đã đề cập trong Javadoc:

connection()
     Không được chấp nhận. (dự kiến ​​gỡ bỏ trong 4.x). Thay thế tùy theo nhu cầu; để sử dụng nội dung JDBC trực tiếp doWork(org.hibernate.jdbc.Work); để mở sử dụng 'Phiên tạm thời' (TBD).

Bạn có một chút thời gian trước Hibernate 4.x, nhưng, bằng cách nào đó, việc sử dụng API không dùng nữa sẽ trông giống như sau:

văn bản thay thế:)

Cập nhật: Theo RE: [hibernate-dev] proxy kết nối trên danh sách hibernate-dev, có vẻ như ý định ban đầu của việc không dùng nữa là không khuyến khích việc sử dụng Session#connection()vì nó / được coi là một API "xấu", nhưng nó đáng lẽ phải ở lại vào thời điểm đó. Tôi đoán họ đã đổi ý ...


2
Javadoc của tôi ở đây hơi khác so với của bạn. Ít rõ ràng hơn một chút: Được thay thế bằng SPI để thực hiện công việc chống lại kết nối; được lên lịch xóa trong 4.x. JavaDoc của bạn nói lên tất cả. JavaDoc này không nói gì.
TraderJoeChi Chicago,

@Sergio Thật vậy. Nhưng nếu tôi có thể, bạn nên đề cập đến những thứ quan trọng như phiên bản Hibernate mà bạn đang sử dụng trong câu hỏi của mình. Phiên bản của bạn khá cũ (javadoc Session#connection()trong Hibernate Core 3.3 đề cập đến phiên bản thay thế) và đó thường là điều mà người đọc không thể đoán được.
Pascal Thivent,

@Pascal Phiên bản 3.2.7.ga là phiên bản mới nhất tôi có thể tìm thấy trên Maven. GroupId = org.hibernate và craftId = hibernate. Tôi tự hỏi nếu Maven có thể cung cấp phiên bản mới nhất hay bạn chỉ cần sao chép cái lọ và bỏ qua maven.
TraderJoeChi Chicago

@Sergio Đó là bởi vì bạn đang sử dụng jar ( hibernate) nguyên khối cũ chứ không phải jar hibernate-corecó các phiên bản mới hơn. Và đối với các phiên bản cuối cùng (3.5.x), chúng có sẵn trong kho lưu trữ JBoss Nexus .
Pascal Thivent

1
@Pascal Cảm ơn! Một vấn đề lớn là tôi cần phải vượt qua kết nối xung quanh, vì vậy nếu Hibernate sẽ không thể cung cấp cho tôi kết nối của nó thì nó sẽ rất tệ. Tôi sẽ cần kết nối này theo cách khác. Tôi nghĩ bất cứ ai có ý tưởng không dùng phương thức kết nối này nên suy nghĩ lại.
TraderJoeChi Chicago

12

Thử cái này

((SessionImpl)getSession()).connection()

Thực tế getSession trả về kiểu Session Interface, bạn nên xem lớp ban đầu của session là gì, gõ ép kiểu lớp ban đầu rồi lấy kết nối.

CHÚC MAY MẮN!


1
❤️ uuuuu rất bực bội vì điều này là cần thiết - cố gắng thiết lập ứng dụng của tôi để thiết lập các kết nối chỉ đọc để phân phối trên các bản sao đã đọc. Cảm ơn.
Sam Berry

1
Tại sao điều này không có nhiều ủng hộ hơn? Có một số lý do mà điều này không nên được thực hiện? Hoạt động hoàn hảo cho tôi.

@tilper SessionImplnằm trong gói Hibernate nội bộ (vì vậy không nhằm mục đích sử dụng) và đó cũng là một phần phụ thuộc vào việc triển khai thực tế. Ngoài ra, bạn không thể mô phỏng phiên trong các bài kiểm tra của mình một cách dễ dàng, khi bạn truyền nó.
Vic,

9

Có một tùy chọn khác với vẫn còn rất nhiều phôi liên quan, nhưng ít nhất nó không cần phản chiếu, điều này sẽ giúp bạn kiểm tra thời gian biên dịch trở lại:

public Connection getConnection(final EntityManager em) {
  HibernateEntityManager hem = (HibernateEntityManager) em;
  SessionImplementor sim = (SessionImplementor) hem.getSession();
  return sim.connection();
}

Tất nhiên, bạn có thể làm cho điều đó thậm chí "đẹp hơn" với một vài lần instanceofkiểm tra, nhưng phiên bản trên phù hợp với tôi.


9

Đây là một cách để làm điều đó trong Hibernate 4.3 và nó không bị phản đối:

  Session session = entityManager.unwrap(Session.class);
  SessionImplementor sessionImplementor = (SessionImplementor) session;
  Connection conn = sessionImplementor.getJdbcConnectionAccess().obtainConnection();

1
Có an toàn để chuyển đổi sessionsang SessionImplementorkhông?
macemers

@DerekY, tôi biết điều này đã cũ, nhưng chỉ cần giải quyết nó bây giờ. Và CÓ, đúng như vậy. Tất cả các triển khai Session cũng là SessionImplementor bằng cách nào đó.
Reginaldo Santos

9

Đây là những gì tôi sử dụng và làm việc cho tôi. Downcast đối tượng Session vào một SessionImpl và dễ dàng nhận được đối tượng kết nối:

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

đâu sessionlà tên của đối tượng phiên Hibernate của bạn.


8

connection()chỉ không được chấp nhận trên giao diện. Nó vẫn có sẵn trên SessionImpl. Bạn có thể làm những gì Spring làm và chỉ cần gọi cái đó.

Đây là mã từ HibernateJpaDialectSpring 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);
        }
    }

15
Đây là loại điều mà Hibernate tuyệt vời khiến bạn phải làm. Rất ít framework tồi như Hibernate.
chrisapotek

8

Tôi tìm thấy bài báo này

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();
    }
}
}

Nó đã giúp đỡ tôi.


6

Với Hibernate> = 5.0, bạn có thể nhận được Connectionnhư sau:

Connection c = sessionFactory.
getSessionFactoryOptions().getServiceRegistry().
getService(ConnectionProvider.class).getConnection();

3

Đối với hibenate 4.3, hãy thử điều này:

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;
    }

1

Thử cái này:

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;
}

0
    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();
        }
    }

0

Đây là một phương thức Java 8 để trả về một phương thức Connectionđược sử dụng bởi một EntityManagermà không thực sự làm gì với nó:

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();
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.