If you’ve done much with Groovy, you probably know about the slick Sql class that it provides for interfacing with a SQL datastore across JDBC. It’s not perfect, but it’s certainly easy. I was working on a Hibernate project and wanted the same thing for my HQL queries, so I threw together a simple Hql class to provide the same sort of behaviour.
Like Sql, it can be parameterized with a connection source (a SessionFactory in this case) or a specific connection (a Session). If given a SessionFactory, it’ll use getCurrentSession() to grab a Session when one is needed, which allows you to wire a single Hql instance up in your Spring config, supply it your SessionFactory, and then inject the Hql into all your persistence-aware beans and just use it.
It also provides a public getSession() method for returning the current session to those same beans, which means you can just inject the Hql instance and not have to also inject the SessionFactory instance if you’re feeling lazy (or doing some quick prototyping). I will leave whether that’s an appropriate long-term approach for a different discussion.
Here she be:
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
/**
* I aim to be sort of like Groovy's builtin Sql class, except for Hql
* @author bboisvert@gmail.com
*
*/
class Hql {
private Session __sess
private SessionFactory __sf
def Hql(SessionFactory sf) {
__sf = sf
}
def Hql(Session s) {
__sess = s
}
SessionFactory getSessionFactory() {
__sf
}
Session getSession() {
__sess ?: __sf.currentSession
}
Object unique(String hql, List params=null) {
new Statement(hql, params).query(session).uniqueResult()
}
Object unique(GString gstring) {
new Statement(gstring).query(session).uniqueResult()
}
List list(String hql, List params=[], Integer firstResult=null, Integer maxResults=null) {
new Statement(hql, params, firstResult, maxResults).query(session).list()
}
List list(GString gstring, Integer firstResult=null, Integer maxResults=null) {
new Statement(gstring, firstResult, maxResults).query(session).list()
}
private class Statement {
String hql
List params
Integer firstResult
Integer maxResults
def Statement(String hql, List params, Integer firstResult=null, Integer maxResults=null) {
this.hql = hql
this.params = params ?: []
this.firstResult = firstResult
this.maxResults = maxResults
}
def Statement(GString gstring, Integer firstResult=null, Integer maxResults=null) {
def hql = new StringBuilder()
def params = []
def prefix
gstring.strings.eachWithIndex { str, i ->
if (i > 0) {
def v = gstring.getValue(i - 1)
if (v != null) {
hql.append(prefix).append("?")
params += v
} else {
if (prefix.trim().endsWith('=')) {
prefix = prefix.replaceFirst(/=(\s*)$/, ' is$1')
}
hql.append(prefix).append("null")
}
}
prefix = str
}
hql.append(gstring.strings.last())
hql = hql.toString()
this.hql = hql
this.params = params
this.firstResult = firstResult
this.maxResults = maxResults
}
Query query(Session sess) {
def q = sess.createQuery(hql)
params.eachWithIndex { o, i ->
q.setParameter(i, o)
}
if (firstResult != null) {
q.firstResult = firstResult
}
if (maxResults != null) {
q.maxResults = maxResults
}
q
}
}
}