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:

  1. JobOrder, more specifically the underlying JOBORDER table and the mechanism to populate that table, is a 3rd party product. You cannot change either.
  2. Rows in JOBORDER may contain PUBLISHEDZIP values which do not exist in your ZIP table.
  3. Your current GORM model does not contain a relationship between JOBORDER and ZIP so you therefore cannot use a Criteria/HQL to select a subset of the data that contains only valid ZIP codes.

Options that might work:

  • make the method you described static so you don't need to instantiate an object of the underlying class.
  • use the inList restriction on your named query (I haven't tested this, but seems like it should 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.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top