Grails accessing relationship tables - grails

I have one many-to-many relationship in my app which looks like this: class
App {
String type
String name
static hasMany = [users: User]
}
class User {
String email
String regid
static belongsTo = App
static hasMany = [apps:App]
}
Now i want to access all Users of an app, by having its id. I prefer using plain SQL as It is working way faster and I database will have ~one million records. So i need a way to access all users of an app where app id in (array of given apps).
What I am trying is doing something like this:
def result = sql.eachRow('SELECT App_Users from App where id in(?)' [id:params.app_checkbox])
But this throws me exception as column App_users is not available.
I am trying to do this for 4-5 hours and bearing in mind I am not a web developer, it is already driving me crazy, so could you guys give me advice, how to access members of many-to-many relationship with sql?

At last i managed to achieve it with simple criteria:
def results = App.createCriteria().list() {
createAlias('users', 'user')
'in'("id", goodIds)
projections {
count('users')
}
}

Related

Grails 3 hasOne nullability issue

While migrating an existing app from Grails 2.5 to 3.1, I ran into an odd issue with a bi-directional one-to-one relationship.
Imagine a simple model with a User and Employee objects. A User represents a generic user account. Not all users are Employees but all Employees are Users. Moreover Employees have references to managers, supervisors, etc (also User instances). User is the owning side of the relationship.
class User {
Employee employee
static mappedBy = [employee: "user"]
static hasOne = [employee: Employee]
static constraints = {
employee(nullable:true)
}
}
class Employee {
User user // represents employee's own account, a bi-directional one-to-one
User supervisor // represents a supervisor
static belongsTo = [user: User]
static constraints = {
user(unique:true)
supervisor(nullable:true)
}
}
The trouble after upgrading to Grails 3 is that in the create mode, this results in supervisor_id column of employee table being generated as NOT NULL, whereas in Grails 2 it was nullable as expected (with only user_id being NOT NULL).
I tested this with Grails 3.1.12 and 3.2.0, getting the same behavior with both. Am I doing anything stupid in my domain class declarations? I've tried multiple mappings to achieve the same behavior as in Grails 2.5 without luck. In some cases I'm even getting a foreign key on both sides of the relationship...
I don't know why your code was working with previous version of Grails, but it is wrong.
When you use hasMany and belongsTo, it is not necessary to define other property in the child object, and you don't need also to use the mappedBy property on the parent, and the same with the parent (property employee at User)
Grails doesn't need anything else to know which is the bidirectional property on both classes, and the constraint user(unique : true) neither.
So your classes should look like this:
class User {
static hasOne = [employee: Employee]
static constraints = {
employee(nullable: true)
}
}
class Employee {
User supervisor // represents a supervisor
static belongsTo = [user: User]
static constraints = {
supervisor(nullable:true)
}
}
It could be nice to know how is your DB structure. But in this way all foreign keys are stored in the employee table. But of course you could navigate from both entities. If you have different structure you could map your current database with this model. See this
employee.user
user.employee

Domain modeling using GORM in grails, how to represent an association

I am learning grails and I came up with a use case. In my use case, a product has many users and each user can have many roles.
Here is my product class:
class Product {
String name
String description
String vision
Date startDate
Date endDate
static hasMany = [users : User, contributors : User, watchers : User, approvers : User]
static belongsTo = User
static constraints = {
}
}
Here is my User class:
class User {
static constraints = {
}
String fullName
String email
static hasMany = [roles : Roles, products : Product]
}
Here is the Roles Enum:
public enum Roles {
PRODUCTOWNER ('ProductOwner'),
APPROVER ('Approver'),
CONTRIBUTOR ('Contributor'),
WATCHER ('Watcher')
}
My question is specifically about the association between Product and User. I want to represent the fact that a product can have many users in different roles. Also, each user can be part of multiple products with a different role in each product. Is this the right way to represent this relationship? Also, I should be able to remove and add users to products and vice versa. What this also means is that, users can keep moving between roles and can move in and out of products. In this scenario, I probably don't want cascades to happen. How do I prevent automatic cascades from happening to CRUD operations for this relationship?
Thanks.
I think rather than having roles and products in User.groovy, it will be better if you create a separate domain like UserProductRole. As you said user will have different role in different products then creating a separate domain makes more sense in business usecase and also doing queries
class UserProductRole{
Role role
static belongsTo = [user:User,product:Product]
static constraints = {
user (unique:['product','role']
}
}
You can create composite key but I generally dont perfer it because it makes querying bit difficult.
And now you need to change hasMany in User and Product like following
[userProducts:UserProductRole] rather then having users or products

Grails - Querying a domain instance's properties' properties

So far all the examples of queries I am coming across are geared towards a domain class such as:
Account.where, Account.withCriteria, Account.findxxxx but what if I want to query an instance's properties' properties? For example what if I have c a company instance that has a department d and I want to get a list of all the departments of this company instance that have 12 employees (a property of department) or less? What would be the code for such a query?
Something like:
c.findAllD's(such that d.numberOfEmployees <= 12)
Also, can anyone point me to literature on such instance based queries? I haven't been able to come across it.
The easiest approach would be to make the association bidirectional, i.e.
class Company {
static hasMany = [departments:Department]
}
class Department {
Company company
int numberOfEmployees
static belongsTo = [company:Company]
}
Then you can simply start your queries from the Department end, such as
def c = Company.get(...) // or however you obtain your Company instance
def departments = Department.findAllByCompanyAndNumberOfEmployeesLessThanEquals(c, 12)
looks like you want to use the Named Queries

Creating one-to-many & many-to-many for same domain class in grails

I want to create a domain class as like , One user can post many orders [Bidirectional] and one order can be liked by many users [unidirectional].
I have written a domain class as shown below ,
Class User {
String userName;
List orders
static hasMany = [Order]
}
Class Order {
String orderId
String orderName
//Indicates this order belongs to only one user
static belongsTo =[owner : User ] // Bidirectional
//Indicates order can be liked by many users
static hasMany = [likedUser : User] //Unidirectional
}
But I am getting am error saying invalid schema . Any body please help...
This post looks similar to my question but I am not getting , Please help.
First, order is a reserved word in SQL. Since GORM by default creates a table with the same name as your class, you'll need to either rename your class or provide a different name to use when mapping to SQL tables.
For example:
class Order {
static mapping = {
table 'user_order'
}
// ...
}
Another problem is that Order contains two associations to User. You need to tell GORM which one of these that is the bi-directional association from User to Order. That can be achieved using mappedBy, like this:
class User {
String userName
static hasMany = [orders: Order]
static mappedBy = [orders: 'owner']
}
Hope this helps.

many-to-many not persisting in gorm/grails app

I have roughly the following in my grails 1.1 app
class AppCategory {
static belongsTo = App
static hasMany = [ apps: App ]
String name
}
class App {
static hasMany = [ categories: AppCategory]
String name
}
App app = new App()
AppCategory appCat = AppCategory.findByName('blah')
app.addToCategories(appCat)
app.save()
The correct tables (app, app_category and app_categories) are created and the columns all seem fine, but I don't end up with any records in the association table and no errors. The app_category table and app table are correctly populated.
Do I need to manually manage a domain object for the association table? Or better yet, am I just missing something totally obvious?
Well, one thing that isn't represented in your example above is that you didn't give a name to your App instance, even though it's a required field (grails fields are nullable:false by default unless you explicitly tell it otherwise). I bet if you check
app.hasErrors()
After your app.save(), that you'll see it does have errors that you can list in the app.errors collection.
Otherwise, what you have is fine, and this code worked fine for me with the domain objects you have above:
AppCategory appCat = new AppCategory(name: "blah")
appCat.save()
assert !appCat.hasErrors()
App app = new App(name: "testApp")
app.addToCategories(appCat)
app.save()
assert !app.hasErrors()

Resources