Reputation: 3169
I have a central class for all Hibernate logic (which I didn't write most of). Let's call it HibCentral
.
My code uses this class to create a query from a SQL string:
public class HibCentral {
...some hibernate setup and other methods...
@Transactional
public Query createSQLQuery(final String sql) {
return getCurrentSession().createSQLQuery(sql);
}
}
getCurrentSession()
just calls sessionFactory.getCurrentSession()
.
My class (let's call it MyClass
) is called by a high level service (Service
). It gets a SQL string, calls this method to get a query, populates its parameters, and sends it back to the service. The service then calls the query using query.list()
.
public class MyClass {
public Query getQuery(Args args) {
Query q = hibCentral.createSQLQuery(getSQLString());
setParameters(q);
return q;
}
}
public class Service {
public void doIt() {
Query q = myClass.getQuery(args);
// some logic
List list = q.list();
}
}
But wait, the session is closed.
I tried to move the list()
call to the Hibernate-logic class as well:
public class HibCentral {
....other methods....
@Transactional
public List list(final Query query) {
return query.list();
}
}
but this produced the same "the session is closed" error.
What do I do to make this work?
Upvotes: 0
Views: 2270
Reputation: 3709
When you use @Transactional
it applies to a method unless you specify @Transactional(propagation=Propagation.REQUIRED)
.
As soon as method call finishes transaction is closed, hence the session. You should create query get the list and return in same method.
@Transactional
public List createSQLQuery(final String sql) {
Query query = getCurrentSession().createSQLQuery(sql);
return q.list();
}
Cheers !!
Upvotes: 0
Reputation: 85779
The problem is that only the methods in HibCentral
class are transactional, which means that the database connection opens and closes for the execution of those methods only. After that, the connection will be closed and any interaction with an Hibernate element like Query
outside those methods won't have a valid connection and you will get those errors.
Solution: move the @Transactional
annotation to a higher level. This should be usually at service layer. If your classes in the service layer interact between each other, then move the @Transactional
to a higher level in order to avoid opening and closing many connections.
Upvotes: 1