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 и не должны быть видны вызывающим методам.