从无状态Bean中获取JDBC Connection对象

时间:2011-07-15 12:43:04

标签: java hibernate jpa jdbc ejb

在无状态会话Bean中注入EntityManager,但我希望获得Connection对象以调用数据库过程。 这有什么解决方案吗?

7 个答案:

答案 0 :(得分:16)

这将是JPA提供商特定的代码。通常,这是通过在EntityManager类上调用unwrap()来完成的。

如果您使用的是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();

请注意,为包含消息的PersistenceException的Hibernate 3.6.5提供的JPA 2.0解决方案将失败

  

Hibernate无法解开接口java.sql.Connection

使用Skaffman提供的代码使其适用于Hibernate(即使对于容器管理的持久性上下文,也验证在3.6.5下工作)。

但是,EclipseLink wiki指出了一些有用的信息 - 如果您使用的是JTA托管数据源,则应使用@Resource注释注入它或使用JNDI查找检索它。只要您需要对数据库执行事务性工作,无论您是从数据源还是从现有数据源获取新连接,都是无关紧要的;无论如何,大多数连接池将提供与当前线程相关联的相同连接(即,实体管理器已经使用的连接)。因此,您可以避免以这种方式展开实体管理器,还可以对数据库执行事务活动;请记住,如果执行此操作,可能无法同步持久性上下文缓存和二级缓存。

答案 1 :(得分:9)

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

    });
}

答案 2 :(得分:7)

JPA API本身似乎没有提供这一点,这并不奇怪,但如果您愿意将代码耦合到特定的实现,那么您可以使用这样的东西(Hibernate):

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

请注意,Hibernate 4中不推荐使用Session.connection()进行删除。请考虑使用Session.doWork()代替。

答案 3 :(得分:2)

您必须使用entitymanager.getDelegate()entitymanager.unwrap(这是更好的方式)获取基础代理,将其投放到特定实现(在Hibernate中称为Session )。然后,您可以调用connection()方法。请注意,这已被弃用,请改用Work类。阅读更多here

答案 4 :(得分:1)

这很棒,你可以在其他地方使用连接对象

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

其中session是Hibernate会话对象的名称

答案 5 :(得分:1)

  

在JPA2.0中,如果需要JDBC则是DTO nomodel或实体查询更多   复杂。有时候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);
       }
    }

答案 6 :(得分:0)

以下是适合我的代码。我们使用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;

    }

}