A oneToMany join in Grails using findAll or HQL - grails

I'm new to Groovy and HQL querying but I can't find a solution to this anywhere so it's driving me nuts.
I have two Domain classes which have a one to many relationship defined (a user can have many companies) and I effectively need to do (what would traditionally be called) 'a table join' but clearly with objects.
The classes go like this:
class User {
transient springSecurityService
static hasMany = [company: Company]
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
...
...
...
}
... and the company class
class Company {
static scaffolding = true
String name
String address1
String address2
String address3
String address4
String postCode
String telephone
String mobile // mobile number to receive appointment text messages to
String email // email address to receive appointment emails to
static hasMany = [staff: Staff]
static belongsTo = [user: User]
...
...
...
}
Gorm has created an user_id field within the company table but any attempt to use this in a query returns an error.
So how would I do something like:
select * from user u, company c, where u.id = c.user_id;
What is the best way to do this?

You can effectively use join on the association something like:
HQL
select * from User as u inner join fetch u.company as companies where u.id = ?
Note that using fetch in the query would eagerly fetch the associated collections of companies for a user
findAll()
User.findAll("from User as u inner join fetch u.company as companies where u.id = ?", [1])
Benefit of using findAll instead of HQL is that you can easily implement pagination something like:
User.findAll("from User as u inner join fetch u.company as companies where u.accountExpired = true", [max: 10, offset: 5])
To get a concrete implementation and really understand things in details I would insist to have a look at findAll and HQL associations.

Related

GORM using foreign key instead of domain object

Say I have a Domain Object User which contains an Organization field. I can map that using a foreign key and let hibernate take care of the rest like so:
class User {
String id
String firstName
Organization organization
static mapping = {
table 'user'
id column: "user_id", generator:'assigned'
organization column: 'organization_Id'
}
}
class Organization {
String id
String name
String address
static mapping = {
table 'organization'
id column: "organization_id", generator:'assigned'
}
}
This works fine, but when I want to query for all users in an organization I might have to do something like this
String orgId = "some id"
Organization org = Organization.findById(orgId)
List<User> users = User.findAllByOrganization(org)
It would be convenient to not have to pass the Organization domain object and instead just pass the Organization.Id which is the foreign key on the User table.
How I want my code to look is the following:
String orgId = "some id"
List<User> users = User.findAllByOrganization(orgId)
After researching, it seems like this is not possible, I need to first query for the Organization and then use that object. Is there a way I am unaware of?
One way I like to do it is to use a proxy of your domain object instead of a hydrated instance of it. You can use load() to obtain the proxy. This means no database call is made as long as you don't access any of the domain object's properties beyond the id.
def users = Users.findByOrganization(Organization.load(orgId))
You can use a Criteria:
String orgId = "some id"
List<User> users = User.createCriteria().list {
organization {
idEq(orgId)
}
}
You have two options there:
add a redundant orgId field to you User class and use it for the
lookup.
Use a fake object for your lookup:
.
Organization org = new Organization()
org.id = 'someId' // looks strange, but you can not use id inside constructor
def users = Users.findAllByOrganization org

HQL Join in Grails

I am trying to execute a query to gather specific data but encountering problems in the query on the on portion of the query. To start off this is my class:
class TimeSlot {
String timeslot_id
String time_chunk_id
String uid
String exam_id
String start_time
String is_special_arrangement
static mapping = {
table 'timeslot'
id name: "timeslot_id", column: "timeslot_id"
version false
}
}
This is the query I'm trying to get working:
TimeSlot.executeQuery("Select t.time_chunk_id, t.uid, t.start_time, t.timeslot_id, t.is_special_arrangement, e.length from TimeSlot t inner join Exams e on t.exam_id = e.exam_id where t.exam_id = ? and t.time_chunk_id = ?", [testArray[i], timeChunkArray[x]])
It's throwing an error on the on portion because it's expecting a clause, but I need the data to specifically pertain to the exam.id comparison of both tables. Is there another way around this or a different way to set up the query so it will work like it does in any SQL editor?
It would be easier if you alter the domain class and add one to many relationship
class TimeSlot {
static hasMany = [examinations:Exams]
Then HQL can be
select ... from TimeSlot t join t.examinations e

Select of hasMany mapping with GORM in Grails

Suppose I have a setup like the following:
class User {
static hasMany = [items : Item];
}
class Item {
String name;
}
I'm trying to select all Users that have an Item in that hasMany mapping. I have an id of an Item, and want to find all users that “have” that item.
Is there a HQL query I can run that will do this or better yet, a built in GORM function that handles this query?
Supposing this were straight SQL I would do something like:
SELECT `user_id` FROM `user_item` WHERE `item_id`=[ID]
Looking in H2 I can write the query
SELECT USER_ID FROM USER_ITEM WHERE ITEM_ID=1;
I can expand this SQL to include the entire user object:
SELECT * FROM user, user_item WHERE user_item.item_id=[item id] AND user.id = user_user.user_items_id;
This HQL will work:
Item item = ...
Item.executeQuery(
'from User u where :item in elements(u.items)',
[item: item])

HQL issue with hasMany String

That's the context of this issue:
I have a Grails class:
class User{
long id
static hasMany = [skills: String]
...
}
I'd like to get users from the db on 2 conditions:
set of ids
set of skills (strings)
I wrote this query that works for the ids, but I can't get the skill part working:
User.findAll( "from User
where id in (5067120,5067121,...5067139)" )
For the moment I'm selecting the Users with the right skills manually after this query, but obviously it's not an efficient solution.
How can I solve this?
Thanks!
This should work:
def ids = [5067120L, 5067121L, ...5067139L]
def skills = ['skill 1', 'skill 2']
def users = User.executeQuery(
'select distinct u ' +
'from User u inner join u.skills skills ' +
'where u.id in (:ids) and skills in (:skills)',
[ids: ids, skills: skills])
Note that you don't need to specify the id field if it's a regular long, Grails does that for you.

How to search an inner class?

I have these classes.
class Author{
Person person
}
class Person{
String lastName
String firstName
String middleName
}
I'd like to query Person and Author.
def persons = Person.findAllByLastNameiLike("${a}")
but it seems I can't do
def authors = Author.findAllByPerson(persons)
Any ideas how I'd do this?
This code shown above does not work
def authors = Author.findAllByPerson(persons)
because findAllBy* works with a single object, not a collection. To find all authors where the Person is any one of those contained in persons use either HQL or a criteria query. For example an (untested) HQL query would look something like:
Author.executeQuery("""
FROM Author a
WHERE a.person IN (:people)""", [people: persons])

Resources