Suppose I have a class User with many Customers (marked with hasMany property).
In the class Customer I mark the owner with belongsTo.
Now when I want to get user's customers I simply write User.read(params.id).customers
I want a pagination in my test project, so reading the entire customer list doesnt make much sense.. I'd use something like Customer.findAllByOwner but this method is such a method is not present..
How do I limit the result set of such a query then (offset and limit)?
package myapp
class User {
...
static hasMany = [customers: Customer]
...
}
package myapp
class Customer {
...
static belongsTo = User
...
}
Correct me if I'm wrong, but the idea in its most simplistic form here is that you want to get a list of Customers based off of the User object.
In that case, change your Customer domain class to something like...
class Customer {
...
static belongsTo = [user: User]
...
}
Then, in your controller you can do something like:
def customerInstanceList = Customer.findAllByUser(User.get(params.id), [max: params.max, offset: params.offset])
Hope this helps.
The name of the property in the Customer that you are trying to access is 'user' instead of 'owner'. If you want the property name to be owner it should be:
static belongsTo = [owner : User]
You can paginate the result set of a dynamic finder by supplying a map containing the pagination parameters as the final parameter.
def customers = Customer.findAllByOwner(user, [max:params.max,
offset:params.offset)
Related
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
I have an Domain Class called Contact with multiple hasMany Relationships and another Domain Class Employee which is part of Concat.
Contact has an table contact and Employee should be mapped on a View which looks like this:
SELECT * FROM contact where employee=1
Employee should have the same columns and Relationship than Contact, how do I write the Domain Classes?
Can I use inheritance?
EDIT
Now I have used inheritance like this:
class Employee extends Contact { }
class Contact{
static mapping = {
tablePerHierarchy(false)
}
}
That works so far, but now I want to add some Relationships to Employee, like this:
class Employee extends Contact {
static belongsTo = [CostCenter ]
static hasMany = [costCenter: CostCenter]
static mapping = {
costCenter joinTable: 'employee_cost_center', column: 'employee_id'
}
}
class CostCenter {
static hasMany = [employees:Employee]
static mapping = {
employeesjoinTable: 'employee_cost_center', column: 'cost_center_id'
}
}
now I have the problem that the table 'employee_cost_center' makes an referen to Contact which is good, but also added 'employee_id':
contact_id
employee_id
cost_center_id
So i could add the relationships to Contact but then I have in CostCenter Contact and not Employee.
How can I add Relationships to Employee?
I think you're on track using inheritance. Since Employee is backed by a database view which selects a subset of Contacts, an Employee is a Contact. So you've got a good candidate for inheritance.
Table-per-subclass inheritance
You described the employee view as follows:
SELECT * FROM contact where employee=1
When using table-per-subclass inheritance the table generated for subclasses contain the following columns:
ID (primary key)
Columns for properties added to the subclass (are not in the superclass), excluding properties for associations.
Since Employee does not, and cannot add, additional properties, the view should only return the primary key.
SELECT id FROM contact where employee=1
I have an article that compares table-per-hierarchy to table-per-subclass inheritance and demonstrates what it looks like at the database level.
Join tables
In your domain class examples you described a join table to create the many-to-many relationship between Employee and CostCenter. Join tables should have two, and only two, columns:
The foreign key (the me domain class)
The foreign key of the other domain class.
So your employee_cost_center table should have the columns employee_id and cost_center_id. If you must specify the join table explicitly, use key instead of column.
costCenter joinTable: 'employee_cost_center', key: 'employee_id'
employees joinTable: 'employee_cost_center', key: 'cost_center_id'
belongsTo
You have Employee belong to CostCenter as so:
static belongsTo = [CostCenter ]
Maybe that's a typo, but if you're not defining a back-reference then the belongsTo should be defined as simply the class, like this:
static belongsTo = CostCenter
I've never used belongsTo this way so I don't know what it looks like in the database. But note that if you have a back-reference, defined like this:
static belongsTo = [costCenter: CostCenter]
Then, your employee view must return a cost_center column.
I have the following:
GroupMember.groovy
public class GroupMember{
String userName
String role
}
GroupProfile.groovy
public class GroupProfile{
List<GroupMember> groupMembers = new ArrayList<GroupMember>()
}
GroupProfileController.groovy
public class GroupProfileController{
def createProfile{
GroupMember groupOwner = new GroupMember()
groupOwner.userName = "testUser"
groupOwner.role = "OWNER"
groupOwner.save()
GroupProfile groupProfile = new GroupProfile()
def members = grouProfile.groupMembers
members.add(groupOwner)
groupProfile.save()
GroupProfile.list() //This list contains my GroupMember instance with the correct info
redirecT(action: myProfiles)
}
def myProfiles={
GroupProfile.list() //This list contains my groupProfile that I made but no GroupMember info
}
}
My GroupProfile won't save my GroupMember info. How can I get my GroupProfile to save the GroupMember info?
The normal way to represent this relationship in grails would be:
public class GroupProfile {
static hasMany = [groupMembers: GroupMember]
}
This will automatically generate a method on GroupProfile called addToGroupMembers that will create the associations. Saving the GroupProfile will also cascade to the group members, so you'll only need to call save once after adding the members.
Note that the groupMembers collection will actually be an instance of Set that doesn't necessarily preserve order. You can explicitly declare the collection as a List to preserve order, but it requires additional overhead including an extra database column, so make sure that's really what you want.
Check out the grails manual in the section on GORM: http://grails.org/doc/latest/guide/GORM.html
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])
I have a class User and a class Category with this mapping :
class User {
String name
Set categories
static hasMany = [categories:Category]
}
class Category{
User user
}
when I querying User :
User.list()
I get a multiple result with the same user :
user1
User1
depending on the categories linked to the user.
but if I execute query :
User.executeQuery("from User user");
it's working fine
Why ?
Thanks.