Reputation: 43
I need to do simple search (Two my example-simple domains and controller action are below). I want to return list of users with firstName, lastName or Car.carName like searchPattern
class User {
String firstName
String lastName
static hasMany = [car : Car]
}
class Car {
User user
String carName
}
def list(String search){
...
def searchPattern = "%" + search + "%"
def domains = User.createCriteria().list(max: max, offset: offset) {
or {
like("firstName", searchPattern)
like("lastName", searchPattern)
car {
like("carName", searchPattern)
}
}
}
It returns incorrect results - doesn't see user, which hasn't got car. Can you help me to change it for correct working? Thanks a lot
Upvotes: 1
Views: 509
Reputation: 43
Thanks a lot to all for your help and for usefull links. This decided my problem:
import org.hibernate.criterion.CriteriaSpecification
.....
def domains = User.createCriteria().list(max: max, offset: offset) {
createAlias('cars', 'c', CriteriaSpecification.LEFT_JOIN)
or {
like("firstName", searchPattern)
like("lastName", searchPattern)
like("c.carName", searchPattern)
}
Upvotes: 0
Reputation: 9885
First you need to set up the domain class associations correctly. It seems you're going for a has-many association between User
and Car
. There are two variations: uni-directional and bi-directional. However, your implementation uses neither. Going with the assumption that you want a bi-directional association, you'll need to modify your Car
class like this:
class Car {
static belongsTo = [user: User]
String carName
}
And for clarity, since a User
has many Car
s, it'd be worth pluralizing the collection name:
class User {
String firstName
String lastName
static hasMany = [cars : Car]
}
For more on associations, you can read my article on the subject.
Next, since you want User
s even if they do not have Car
s, you should know about a subtle default built into GORM: the SQL database tables are automatically INNER JOINed. It is this INNER JOIN that's causing User
s without Car
s to be ignored. To address this, you'll need to change the join to an OUTER JOIN. You can do something like this:
import static org.hibernate.sql.JoinType.*
def domains = User.createCriteria().list(max: max, offset: offset) {
createAlias('cars', 'c', LEFT_OUTER_JOIN)
or {
like("firstName", searchPattern)
like("lastName", searchPattern)
like("c.carName", searchPattern)
isNull("c.carName")
}
}
If I recall, aliases are used differently, hence the c.carName
. You can read a bit more about using a LEFT OUTER JOIN here.
Upvotes: 0
Reputation: 20699
try this one:
car{
or{
isNull 'carName'
like 'carName', searchPattern
}
}
Upvotes: 1