JPA createQuery工作但createCriteria不工作会话是关闭错误

时间:2014-03-13 04:52:36

标签: java hibernate jpa createcriteria createquery

我试图通过从EntityManager获取hibernate会话来使用来自Hibernate的Criteria API,如下所示

public org.hibernate.Criteria getCriteria() {
    HibernateEntityManager hem = em.unwrap(HibernateEntityManager.class);
    org.hibernate.Session session = hem.getSession();
    return session.createCriteria(getEntityBeanType());
}

在createCriteria返回时,我收到“会话已关闭错误”。

从我调用getCriteria的代码的相同点,如果我将createQuery方法称为

getEntityManager().createQuery(".....");

它工作正常,我可以在数据库上选择。

我想使用Hibernate Criteria API,因为我很满意。

3 个答案:

答案 0 :(得分:1)

这里的重点是Criteria对象仅在Session对象打开时存在,如果Session对象已经关闭Criteria对象不起作用,有一个名为DetachedCriteria的类允许开发人员创建Criteria在Session对象之外的查询然后将它们附加到它并能够运行。阅读有关已分离here

的更多信息

当休眠会话不存在时,分离标准是非常好的替代

你可以使用这样的东西。

//Not required a session open
DetachedCriteria query = DetachedCriteria.forClass(Employee.class);
query.add(Property.forName("name").eq("Som"));

//Here we open the session
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
List<Employee> employeeList = new ArrayList<Employee>();

//Then we associate the criteria query with the session and run it
employeeList = query.getExecutableCriteria(session).list();
Iterator it = employeeList.iterator();

答案 1 :(得分:0)

在创建条件之前确保您的会话已打开

public org.hibernate.Criteria getCriteria() {

    HibernateEntityManager hem = em.unwrap(HibernateEntityManager.class);
    org.hibernate.Session session = hem.getSession();

 if(session.isOpen())
{
return session.createCriteria(getEntityBeanType())
}

    return null;
}

检查您的日志以获取更多信息,并在此处共享相同内容,这将有助于我们调试...

答案 2 :(得分:0)

我一直在看同样的问题。它来自于@Transactional注释的不当使用。这就是我在做的事情:

doStuff(String[] ids) {
  Criteria criteria = dao.createCriteria(Widget.class); // Session still open here.
  criteria.add(Restrictions.in("widgetId", ids)); // This closed the session!
  ...
}

事实证明,我的dao类使用@Transactional注释进行了注释。因此,只要我尝试使用我的Criteria执行某些操作,它就会先关闭事务,然后关闭会话。解决方案是摆脱dao的createCriteria()方法并向dao添加一个方法,该方法使用Criteria实例完成所有工作。

doStuff(String[] ids) {
  List<Widget> = dao.getWidgetsFromIds(ids); // Do everything inside the transaction
  ...
}
----
// This is in the DAO:
public List<Widget> getWidgetsFromIds(String[] ids) {
  Criteria criteria = dao.createCriteria(Widget.class); // Session is open here.
  criteria.add(Restrictions.in("widgetId", ids)); // Session still open
  ...
}

我构建代码的方式,标准应该是DAO的内部细节,并且不应该对调用方法可见。

相关问题