HQL issue with hasMany String - grails

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.

Related

Getting the latest 10 registered users - Spring security Grails

I need to get the last 10 registered users (normal users) in my application for statistics. The application has two roles: normal user and administrator user.
In my User class (Spring security), I have the dateCreated field and I can obtain the last 10 registered users in my controller with this query:
User.listOrderByDateCreated(max: 10, order: 'desc')
But I just want to get it between normal users, excluding administrator. With this query, I can obtain all normal users:
UserRole.findAllByRole(role).user
What query have I to run? Thanks.
Try this
> User.executeQuery( "from User user where user.id in (select userRole.user.id from UserRole userRole where userRole.role.id =:roleId) order by dateCreated desc", [roleId: role.id], [max: 10])
Other way is
UserRole.executeQuery( "select ur.user from UserRole ur where ur.role.id =:roleId) order by ur.user.dateCreated desc", [roleId: role.id], [max: 10])
Let me know if it works for you .. :)
Surprisingly this is a tricky one, because User doesn't have a direct handle on Role, so the GORM helpers don't help as much. Using straight Groovy list manipulation we can get what you want.
def users = User.list().findAll { it.authorities.contains role }
.sort { it.dateCreated }
.reverse()
.take(10)
//or…
def users = UserRole.findAllByRole(role).user
.sort { it.dateCreated }
.reverse()
.take(10)
However, if you have a large number of users this would be an inefficient way to get 10 of them. A better option may be to use Hibernate criteria:
def users = UserRole.createCriteria().list(max: 2) {
eq "role", role
user {
order 'dateCreated', 'desc'
}
projections { property 'user' }
}
Or if you want, you can query using HQL via executeQuery():
def users = User.executeQuery("from User where id in (select user.id from UserRole where role.id = :roleId) order by dateCreated desc", [roleId: role.id], [max: 10])
Try this:
User.findAllByRole(role,
[max: 10, sort: "dateCreated", order: "desc"])

A oneToMany join in Grails using findAll or HQL

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.

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])

Symfony and DQL syntax

I apologize for the beginner question, but I'm struggling with what seems should be a simple query. I can get it to work perfectly in MySQL, but can't get it to work in my symfony application. Essentially, this is all I'm trying to do:
SELECT *
FROM benefits b
WHERE b.company_id = X
X =
SELECT id
FROM company c
WHERE c.user_id = ($this->getUser()->getGuardUser()->getId())
I've tried many join statements but still can't get it to work with the result I want, such as:
public function executeIndex(sfWebRequest $request)
{
$this->benefitss = Doctrine_Core::getTable('benefits')
->createQuery('b')
->where('user_id = ?', '$this->getUser()->getGuardUser()->getId()')
->leftJoin('b.Company c')
->andWhere('c.user_id = ?', '$this->getUser()->getGuardUser()->getId()')
->execute();
}
Here's my condensed schema:
Benefits
columns
id
user_id
company_id
name
relations
User {class: sfGuardUser}
Company
Company
columns
id
user_id
name
relations
User {class: sfGuardUser}
sfGuardUser
columns
id
also of note: the user is not assigned a company_id b/c not all users will have companies according to my user definitions.
Any help for this wretched beginner would be much appreciated. :)
Update 8/27/11:
This gets the results I want:
$this->benefitss = Doctrine_Core::getTable('benefits')
->createQuery('b')
->leftJoin('b.Company c')
->Where('c.user_id = ?', '1')
->execute();
Where the '1' needs to be the current user's id. But when I change the where clause to:
->Where('c.user_id = ?', '$this->getUser()->getGuardUser()->getId()')
I get no results.
Any ideas?
Don't put $this->getUser()->getGuardUser()->getId() in ''.
I got it figured. Here's how (I'm obviously a beginner):
$this->benefitss = Doctrine_Core::getTable('benefits')
->createQuery('b')
->leftJoin('b.Company c')
->Where('c.user_id = ?', $this->getUser()->getGuardUser()->getId())
->execute();

Help with Creating Models for Views

I am trying to create a Model to pass to a gsp view. I would like to do a sub query across two tables. I have two domains, alum_profile and alum_position. alum_profile has many alum_position's. alum_position belongs to alum_profile. In SQL if I wanted to create a result set, I would have something like this:
Select count(id),
(Select CONCAT(first_name, ' ', last_name)
From alum_profile
where
alum_profile_id =alum_profile.id ) as Person
FROM alum_position
GROUP BY alum_profile_id
ORDER BY count(id) DESC
How do I do this with HQL and create a model that can be passed to a gsp View.
Thanks for your help
jason
I am using Spring Source, with MySQL and writing in groovy on grails
From what I've read of your question, you want to display a list of the Profile's names, along with how many Positions each Profile has, sorted by the number of positions, desc.
First, you need Models:
class AlumProfile {
String first_name
String last_name
def hasMany = [positions: AlumPosition]
};
class AlumPosition {
String name // I just added this, no idea what you need in here
def belongsTo=AlumProfile
};
Now you want to create a list of the AlumProfiles sorted by position count. In your controller, you need:
def allByPositionCount = {
def profiles = AlumProfile.list().sort( [compare: { a,b -> a.positions.size().compareTo( b.positions.size() ) }] as Comparator );
[ profiles: profiles ]
}
This will render the allByPositionCount.gsp with the model containing the "profiles" member that is the list of profiles in the correct order, so something like:
<g:each in="${profiles}" var="profile" >
${profile.first_name} ${profile.last_name} has ${profiles.positions.size()} positions
</g:each>
should render what you want.

Resources