JPA createQuery работает, но createCriteria не работает сеанс закрыт ошибка

Я пытаюсь использовать Criteria API из Hibernate, получая сеанс Hibernate от EntityManager следующим образом

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 ответа

Решение

Убедитесь, что ваша сессия открыта, прежде чем создавать критерии

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

Проверьте ваш журнал для получения дополнительной информации и поделитесь тем же здесь, и для нас будет полезно отладить...

Дело в том, что объект Criteria существует только тогда, когда объект Session открыт, если объект Session был закрыт. Объект Criteria не будет работать, существует класс с именем DetachedCriteria это позволяет разработчику создавать запросы Criteria вне объекта Session, затем прикреплять их к нему и запускать. Узнайте больше о Detached здесь

Отдельные критерии - очень хорошая альтернатива, когда сеанс гибернации отсутствует

Вы можете использовать что-то вроде этого.

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

Я видел ту же проблему. Это происходит из-за неправильного использования аннотации @Transactional. Вот что я делал:

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

Оказывается, мой класс дао был аннотирован @Transactional аннотаций. Поэтому, как только я попытался что-то сделать с моими Критериями, он сначала закрыл транзакцию, которая закрывает сеанс. Решение было избавиться от дао createCriteria() method и добавить метод в 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 и не должны быть видны вызывающим методам.

Другие вопросы по тегам