First I need to apologize for the long post, I struggle with being overly verbose and yet not always clear enough. I also have searched extensively for an elegant solution for my issue and if I missed it please direct me to it.
Some Background:
I have a grails app that is using namedQueries for a set of standard result sets. The app finds open advertised Job Orders in our system and sends them to other sites. Recently an additional requirement has become a problem for me if I wish to continue using the namedQueries.
For the sake of simplicity let's just assume a domain model of
class JobOrder {
def getOpenAdJobsSql() {
def qry = "select jo FROM JobOrder jo WHERE isOpen=1 AND publishedTo='All External' AND adCategory.isActive=1 AND jo.adLocation in (select zc.id from Zip zc)"
JobOrder.executeQuery(qry)
}
static namedQueries = {
openAdJobs {
eq 'isOpen', true
eq 'publishedTo', "All External"
adCategory {
eq 'isActive', true
}
}
static mapping = {
table 'dbo.JOBORDER'
version false
id generator: 'identity', column: 'JOBORDERID'
isOpen column: 'ISOPEN'
publishedTo column: 'customText15'
adLocation column: 'PUBLISHEDZIP'
adCategory column: 'customInt3'
}
Boolean isOpen
String publishedTo
String adLocation
ClientCorporation client
AdCategory adCategory
static constraints = {
adLocation(size: 0..100)
}
}
class AdCategory {
static mapping = {
table 'dbo.AdCategory'
version false
id generator: 'identity', column: 'adCategory_ID'
isActive column: 'active'
}
}
class Zip {
static mapping = {
table 'ZIP'
version false
id generator: 'identity', column: 'ZIPCODE'
city column: 'city'
county column: 'county'
stateAbbr column: 'statecode'
}
String city
String county
String stateAbbr
}
I will begin with the current namedQuery in concern:
openAdJobs {
eq 'isOpen', true
eq 'publishedTo', "All External"
adCategory {
eq 'isActive', true
}
}
This query exists in my JobOrder domain object which also has a relationship with the AdCategory domain object. The named query is called in multiple places using the following call:
def openJobs = JobOrder.openAdJobs
My New Problem:
Now I have a requirement to make sure I don't publish any jobs that have invalid zip codes. I am integrating with a product which contains no zip validation and I have no control over the product's native domain model. We have added a custom Zip domain object that is stand alone. I have struggled figuring out a way to include code that will work with the named query in my JobOrder object to accomplish what the following query would return: (i run this query against the sql db in dbvisualizer)
select * from dbo.JobOrder jo
inner join dbo.AdCategory ac on jo.adCategory=ac.adCategory_ID
where
jo.isOpen=1
and
jo.publishedTo='All External'
and
ac.isActive=1
and
jo.publishedZip in (
select zc.zipcode from dbo.Zip zc
)
A not-so-pretty solution:
The only way I and a couple of peers have gotten the desired result set is by creating a method like the following in my JobOrder object:
def getOpenAdJobsSql() {
def qry = "select jo FROM JobOrder jo WHERE isOpen=1 AND publishedTo='All External' AND adCategory.isActive=1 AND jo.adLocation in (select zc.id from Zip zc)"
JobOrder.executeQuery(qry)
}
The method, of course, is not available unless I instantiate a JobOrder. Since I am actually attempting to build my list of JobOrders at this point there is a very unappetizing hack to get my result set. I would need to fetch a known good JobOrder (or create one) so the getOpenAdJobsSql() method is available to call.
something like:
def jo = JobOrder.get(2)
def rset = jo.openAdJobsSql
would need to be added everywhere I currently call the openAdJobs named query (currently 9 or more usages). To even consider this approach is sending mental warning flares up for me, but I see no other way to add the additional feature.
Again, ultimately it is my desire to call a named query, but the additional zip code sql appears to be something GORM + hibernate is not going to be able to handle.
It is my hope that someone will know of a more elegant solution. And please ask for clarity anywhere it is missing in this post.
Okay, so if I understand your problem:
Options that might work:
.
openAdJobs {
eq 'isOpen', true
eq 'publishedTo', "All External"
inList 'adLocation', Zip.list()
adCategory {
eq 'isActive', true
}
}
I think there is probably a better performing alternative that you could use involving a Subquery expression that replaces the inList with an Exists clause, but off the top of my head I'm not sure if CriteriaBuilder/GORM Criteria supports that or not. You might have to get down into the Hibernate to do that and I'm not sure how well that approach plays with named queries.