1

Let say I have the following domain model :

class Book {
  String title
  Set authors

  static hasMany = {authors: Author}
}

class Author {
  String name
}

The HQL query to retrieve a collection of Author given a query on a title Book:

Author.executeQuery("select distinct author from Book as book join book.authors as author where book.name like ?", ["%groovy%"])

But I would to be able to have the same result a with DetachedCriteria or alike (but is it possible ... ?) and without adding a relationship from Author to Book (otherwise it would pretty obvious)

thanks

Jean-Baptiste
  • 387
  • 3
  • 11

2 Answers2

1

This can be done a few ways with criteria or detached Criteria, but a bit easier with regular GORM criteria since it implements the createAlias command that detachedCriteria doesn't as of Grails 2.2.2:

Create Alias In Detached Criteria

Here are both ways:

package bookauthor

import grails.gorm.DetachedCriteria
import grails.orm.HibernateCriteriaBuilder


class MyController {

def index() {
  HibernateCriteriaBuilder ac2 = Author.createCriteria()
  HibernateCriteriaBuilder criteria2 = Author.createCriteria()

  HibernateCriteriaBuilder criteria = Book.createCriteria()

  def bookResults = criteria {
    projections {
      property 'aut.id'
    }
    createAlias('authors',  'aut')
    like('title', '%Groovy%')

  }

  def dc = new DetachedCriteria(Book).build {
    authors {}
    like('title', '%Groovy%')
  }

  def myList = dc.list().collect { it.authors.collect { author -> author.id} }.flatten()

  def resultsDetached = criteria2 {
    'in'('id', myList )
  }

  def results = ac2 {
    'in'('id', bookResults )
  }
log.info("RESULTS: " + results)
log.info("Detached RESULTS: " + resultsDetached)
}  

}

You'll see in the logs:

bookauthor.MyController  - RESULTS: [bookauthor.Author : 1, bookauthor.Author : 3]
bookauthor.MyController  - Detached RESULTS: [bookauthor.Author : 1, bookauthor.Author : 3]
dkstyle0
  • 51
  • 2
1

Unfortunately, AFAIK, this is not possible with this query. It's possible with the following ugly query, though:


select author from Author author
where author.id in (select author2.id from Book book
                    join book.authors as author2 
                    where book.name like :bookName)

For such a simple, non-dynamically composed query, I would stick with your HQL query. If you really need to use Criteria, then this is the corresponding code:


Criteria c = session.createCriteria(Author.class, "author");
DetachedCriteria dc = DetachedCriteria.forClass(Book.class, "book");
dc.createAlias("book.authors", "author2");
dc.add(Restrictions.like("book.name", bookName));
dc.setProjection(Projections.property("author.id"));
c.add(Subqueries.propertyIn("author.id", dc);
List<Author> authors = (List<Author>) c.list();

IgniteCoders
  • 4,834
  • 3
  • 44
  • 62
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • These are hibernate Criteria and DetachedCriteria query ? not GORM Criteria and DetachedCriteria ? Do you have a clue how to write the same with de Grails/GORM Criteria and DetachedCriteria ? – Jean-Baptiste Jan 20 '12 at 16:58
  • No. I assumed that GORM was just a wrapper around Hibernate's Java API. – JB Nizet Jan 20 '12 at 17:04