1

I am running a Spring + Hibernate web application on Tomcat 7.0.35 (Spring 3.1, Hibernate 3.6.1, JPA 2.0).

This app has a page that gets data from the database via Hibernate's Criteria (I know I dont have to). The service tier simply calls the data tier. Here is the code:

    Criteria criteria = sessionFactory.openSession().createCriteria(Article.class); 
    criteria.addOrder(Order.desc("updatedTime"));
    criteria.add(Restrictions.eq("account", acc));
    criteria.add(Restrictions.eq("draft", true));
    criteria.setMaxResults(1);
    Article s = (Article) criteria.uniqueResult();
    return s;

Tomcat can only serve a few requests from this page, and then it becomes non-responsive. I can see the browser keeps waiting for server response (Firefox status bar shows "waiting for host".)

I am not seeing any error message such as OutOfMemory, etc. It appears that the browser waits forever.

If I change it to JPA as follows:

    @NamedQuery(name = "Article.getMostRecentDraftArticle", query = "select x from Article x where x.account = :account and x.draft = 1 order by x.updatedTime desc"),

.....

Query q = getSession().getNamedQuery("Article.getMostRecentDraftArticle");
q.setParameter("account", acc);     
q.setMaxResults(1);
List list = q.list();
if (list.size() == 0) 
    return null;
else 
        return (Article) list.get(0);

Then everything works right.

What could go wrong with my use of Hibernate's Criteria API?

Thanks for any input!

Cheers.

curious1
  • 14,155
  • 37
  • 130
  • 231

2 Answers2

2

You haven't closed the session. See this answer: https://stackoverflow.com/a/4049758/116509

and read the javadoc of org.hibernate.session:

A typical transaction should use the following idiom:

 Session sess = factory.openSession();
 Transaction tx;
 try {
     tx = sess.beginTransaction();
     //do some work
     ...
     tx.commit();
 }
 catch (Exception e) {
     if (tx!=null) tx.rollback();
     throw e;
 }
 finally {
     sess.close();
 }
Community
  • 1
  • 1
artbristol
  • 32,010
  • 5
  • 70
  • 103
  • Tried this solution by adding sessionFactory.openSession().close(); before return. But it does not work. – curious1 Apr 15 '13 at 16:22
  • You need to call `close` on the same instance. Calling `openSession` again will create a different instance. – artbristol Apr 15 '13 at 17:20
1

Can you see the hibernate logs? does it generate the query?
Anyway, you can try to put a sessionFactory.getCurrentSession().flush(); below Article s = (Article) criteria.uniqueResult();

cloudy_weather
  • 2,837
  • 12
  • 38
  • 63
  • By the way, why do you have both `criteria.setMaxResults(1);` and `criteria.uniqueResult();`? only the second should be enough. Isn't it? – cloudy_weather Apr 15 '13 at 16:38
  • 1
    as a desperate attempt, if after the flush you add `sessionFactory.getCurrentSession().clear();` it might help. But pay attention because the clear detaches all the instances and deletes all the pending updates, it clears the session. – cloudy_weather Apr 15 '13 at 16:42
  • daniele, thanks for your input. I used the session.close as suggested by artbristol. it worked. – curious1 Apr 15 '13 at 18:05