What is the purpose of the Hibernate ReturningWork<Long> interface?
Hibernate Session Hibernate Session
doReturningWork
The Hibernate Session
doReturningWork
method has the following signature:
<T> T doReturningWork(ReturningWork<T> work) throws HibernateException;
And the ReturningWork
interface looks as follows:
public interface ReturningWork<T> {
public T execute(Connection connection) throws SQLException;
}
So, unlike the doWork
method, the doReturningWork
allows us to return an object to the method caller.
For example, we can use the doReturningWork
method to get the current transaction isolation level:
Session session = entityManager.unwrap(Session.class);
int isolationLevel = session.doReturningWork(
connection -> connection.getTransactionIsolation()
);
assertEquals(
Connection.TRANSACTION_READ_COMMITTED,
isolationLevel
);
When to use doWork
and doReturningWork
?
In general, you can use the JPA or Hibernate-specific API to execute SQL statements or call database procedures or functions.
However, if you want to get access to the underlying JDBC Connection
method and execute any possible operation via the JDBC API, then you need to use the doWork
and doReturningWork
Hibernate Session
methods.
As I explained in more details on my blog, you can use the ReturningWork
and the Work interfaces to implement any logic that requires direct access to the java.sql.Connection
used by your Hibernate session.
Here is a simple example that uses the ReturningWork
interface to execute a very simple query (which you could also implement with JPQL) and return the result.
Session session = em.unwrap(Session.class);
Integer bookCount = session.doReturningWork(new ReturningWork<Integer>() {
@Override
public Integer execute(Connection con) throws SQLException {
// do something useful
try (PreparedStatement stmt = con.prepareStatement("SELECT count(b.id) FROM Book b")) {
ResultSet rs = stmt.executeQuery();
rs.next();
return rs.getInt(1);
}
}
});
log.info("Found " + bookCount + " books.");