如果我有实体管理器,如何获取会话对象?

124

I have

private EntityManager em;

public List getAll(DetachedCriteria detachedCriteria)   {

    return detachedCriteria.getExecutableCriteria("....").list();
}

如果我使用entitymanager,我该如何检索会话?或者我该如何获取来自我的脱离标准的结果?

如何在使用EntityManager时检索会话或从分离的标准中获取结果?


请参见((EntityManagerImpl)em).getSession(); - ashley
6个回答

204
要完全详尽,如果你使用的是JPA 1.0或JPA 2.0的实现方式,情况会有所不同。
JPA 1.0
在JPA 1.0中,你需要使用EntityManager#getDelegate()。但请记住,该方法的结果是与具体实现相关的,即从使用Hibernate的应用服务器到其他服务器之间不可移植。例如,在JBoss上你可以这样做:
org.hibernate.Session session = (Session) manager.getDelegate();

但是使用GlassFish,你需要做以下操作:
org.hibernate.Session session = ((org.hibernate.ejb.EntityManagerImpl) em.getDelegate()).getSession(); 

我同意,那真是太糟糕了,这里的问题在于规范不够清晰。
JPA 2.0
在JPA 2.0中,有一个新的(而且更好的)EntityManager#unwrap(Class<T>)方法,对于新应用程序来说,它是首选,而不是EntityManager#getDelegate()
所以,如果使用Hibernate作为JPA 2.0的实现(参见3.15. Native Hibernate API),你可以这样做:
import org.hibernate.Session;
...

Session session = entityManager.unwrap(Session.class);

2
entityManager.unwrap(Session.class); 中的 Session 是什么?它是一个导入吗? - Thang Pham
1
根据JPA实现的不同,如果你使用的是EclipseLink,那么它就是org.eclipse.persistence.sessions.Session - albciff
我不得不在一个使用entityManager.unwrap(Session.class)的存储库类上放置@Transactional。否则,我会遇到java.lang.IllegalStateException: No transactional EntityManager available错误。 - Dima Korobskiy

49
请参阅《Hibernate ORM用户指南》中的"5.1. 从JPA访问Hibernate API"部分:链接
import org.hibernate.Session;
...

Session session = entityManager.unwrap(Session.class);

entityManager.unwrap(Session.class); 中的 Session 是什么?它是一个导入吗? - Thang Pham
2
Hibernate手册已经改变。第15.8点不再提供有关获取会话的任何信息。 - Nicktar
3
截至2019年1月,Hibernate最新手册(版本5.3.7),第5.1节仍然将此作为获取Session对象引用的方式。 - Alain BECKER

7
这将更好地解释。
EntityManager em = new JPAUtil().getEntityManager();
Session session = em.unwrap(Session.class);
Criteria c = session.createCriteria(Name.class);

Session类从哪里导入的?从你妈妈家吗?请具体说明,不要只是复制粘贴。 - TheRealChx101

3

'entityManager.unwrap(Session.class)' 用于从 EntityManager 中获取 Session。

@Repository
@Transactional
public class EmployeeRepository {

  @PersistenceContext
  private EntityManager entityManager;

  public Session getSession() {
    Session session = entityManager.unwrap(Session.class);
    return session;
  }

  ......
  ......

}

演示应用程序 链接.


0
如果您正在使用Hibernate 5,仅使用EntityManager.unwrap()可能无法正常工作,这是由于Spring的代理行为和Hibernate最近的更改(请参见this Spring issue,已修复但实际上并没有)。

为了使其正常工作,我必须首先使用null进行双重解包:

/**
 * Get the Hibernate {@link Session} behind the given {@link EntityManager}.
 *  
 * @see <a href="https://github.com/spring-projects/spring-framework/issues/19577">Spring Issue #19577</a>
 */         
public static Session getHibernateSession(EntityManager entityManager) {
    Preconditions.checkArgument(entityManager != null, "null entityManager");
    return ((EntityManager)entityManager.unwrap(null)).unwrap(Session.class);
}

我相信这是由于Spring的ExtendedEntityManagerCreator中代理的unwrap()方法的处理方式所致:

...
else if (method.getName().equals("unwrap")) {
    // Handle JPA 2.0 unwrap method - could be a proxy match.
    Class<?> targetClass = (Class<?>) args[0];
    if (targetClass == null) {
        return this.target;
    }
    else if (targetClass.isInstance(proxy)) {
        return proxy;
    }
}

-2

我曾经在Wildfly上工作,但是我使用的是

org.hibernate.Session session = ((org.hibernate.ejb.EntityManagerImpl) em.getDelegate()).getSession();

而正确的写法是

org.hibernate.Session session = (Session) manager.getDelegate();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接