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()
Related
I have an existing application with the following domain classes/relations:
class Contact {
static hasMany = [phones: Phone]
}
I would like to modify the structure to allow for a delete flag to be set in the Phone class and then not have to modify existing calls to the getter for phones to get phones that have not had that delete flag set.
ex:
contact.phones
I have seen a post on this site detailing how to do this.
StackOverflowPost
I have tried that approach(modifications showed below) but GORM is behaving oddly by incrementing the version when it shouldn't be. I'll hit the contact edit page and then when a version comparison is done on the server after submitting the form the version in the DB has incremented up about 5 or 6 times compared to the version value that was passed to the edit.gsp. I have also applied this pattern to two more relations so I'm thinking they are also causing the version to increment. I'm going to test with only one domain relation modification to see if I can find a pattern. Does anyone have any ideas as to the right way to do this or how to avoid version incrementing?
class Contact {
Set<Phone> phones
static hasMany = [phones: Phone]
Set<Phone> getPhones() {
phones.findAll { !it.deleted }
}
}
Not a direct answer to your question, but i use methods in my class, which instead of returning the actual domain instances, returns the detached criteria that callers can use, add new restrictions, and finally get the results.
class Contact {
DetachedCriteria<Phone> phones() {
def criteria = new DetachedCriteria(Phone).build {
eq "deleted", false
eq "contact", this
}
return criteria
}
}
The contact class will return a criteria with main restrictions added, and callers can add more restrictions if they have to.
List phones = contact.phones().list()
or
List phones = contact.phones().list {
eq "country", "xxx"
}
This gives callers more flexibility.
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
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')
}
}
I have set up a one-to-many relationship in my scaffolded Grails application:
class Course {
County county
Date date
int maxAttendance
static hasMany = [ persons:Person ]
}
class Person {
String firstName
String lastName
String email
Course course
boolean attended
boolean paid
static belongsTo = [ class:Course ]
}
So, when a user views the CourseController, they are able to see Person's registered in the selected Course.
My question is, how can I change the application so that when a user views the people in a given course, they can also view/modify the checkboxes for 'boolean attended' and 'boolean paid', which are also in the Person domain? Here is a screenshot:
The thing is that you are using the scaffolded view, so you are pretty much stuck with the default design.
You can modify the behaviour, by installing and modifying the templates that grails uses to generate those views:
grails install-templates
This will create the templates in src/templates/scaffolding, although I do not recommend that approach. Maybe it is time that you start developing your own controllers and views, since the scaffolding is there mainly for testing and for administrative use.
Grails 2.0.1
Here are stripped down simplified versions of the Domains:
class Attribute {
String name
static hasMany = [attributeParameters: AttributeParameter]
}
class AttributeParameter {
String name
Attribute attributeReference
static belongsTo = [attribute:Attribute]
}
When I look at the schema in the database, there are 2 separate FKs in AttributeParameter; 1 for the attribute_reference_id, and one for attribute_id. When I save the domains populated with all their data I am getting 0 errors on both Attribute and AttributeParameter, however, the attribute_reference_id column never gets populated. Debugging, I can see the attributeReference object and it has an ID, even after the save call(s). Grails is not throwing any exceptions (at least none that are being displayed on the console).
Stranger still is that if I go to the database and add the ID of an attribute into the attribute_reference_id column, GORM loads it perfectly. Hitting save again, it goes back to null even though debugging shows the object present.
Really at a loss as to why the data isn't persisting.
I had to add the following to Attribute:
static mappedBy = [attributeParameters: 'attribute']