How to save associated object in Grails? - grails

I am a grails beginner.
i have a 2domain class
class Employee {
String name
String department
static constraints = {
}
public String toString() {
name
}
}
class Address {
String line1
String line2
Employee employee
static belongsTo = Employee
static constraints = {
}
}
where Address belongs to Employee .. so i have given belongsTo association.
My Employee/create.gsp page takes input for fields specified in Employee and Address.
so on creation of employee , address must be get save automatically .
so what could be the save action in EmployeeController
i have tried some thing like this but did not work.
def save = {
def employeeInstance = new Employee(params)
def addressInstance = new Address(params)
if (employeeInstance.save(flush: true)) {
flash.message = "${message(code: 'default.created.message', args: [message(code: 'employee.label', default: 'Employee'), employeeInstance.id])}"
redirect(action: "show", id: employeeInstance.id)
}
else {
render(view: "create", model: [employeeInstance: employeeInstance])
}
}
how to save this associated model ?

Here you have a one-to-one relationsip - add an address property to the Employee class.
class Employee {
String name
String department
Address address
public String toString() {
name
}
}
Change your belongsTo of the Address like this:
class Address {
String line1
String line2
static belongsTo = [employee: Employee]
}
Now you could create an Employee like this:
def employeeInstance = new Employee(params)
employeeInstance.address = new Address(params)
if (employeeInstance.save(flush: true)) {
// your logic
}
Read the docs (one-to-one relationship) for further informations.

Related

Grails search from one to many is not working

Here are my domain class,
class Company {
String name
static hasMany = [groups:CompanyGroup]
}
class CompanyGroup{
String name
static belongsTo = [company:Company]
}
I receive params that contain name of CompanyGroup and I want to get the result of company that have the CompanyGroup found.
I did like this,
def groupList = account.companies.groups.flatten()
def groupResult = groupList.findAll{
it.name ==~ /(?i).*${params.keyword}.*/
}
I got the Companygroups that have name from params.key from above code. So I want to render company list that have these group like this,
def com = Company.withCriteria{
eq("groups", groupList)
}
render [companies : com]
It doesn't work!
def com = Company.withCriteria{
inList("groups", groupList)
}

Field values rendered null when using HTTP GET call in grails

This is domain class of Person :
package com.sample
class Person {
String id
String name
Integer age
Address address
static hasMany = [pets:Pet, alias: String, aliases : Alias]
static mapWith = "mongo"
static constraints = {
address nullable:true
pets nullable :true
}
}
This is the domain class of Address :
package com.sample
class Address {
String address
static mapWith = "mongo"
static constraints = {
address maxSize: 1000
}
}
This is ShowPerson method in PersonController:
def showPerson(String name,String age){
if(Person.findByAgeAndName(age,name) != null) {
render Person.findByAgeAndName(age,name) as JSON
}
else {
def addobj = new Address(address: "kondapur")
addobj.save(flush:true)
def pet1 = new Pet(name : "Dog", breed : "A")
pet1.save(flush:true)
def alias1 = "ALIAS1"
def alias2 = "ALIAS2"
def list = ["A"]
def aliases1 = new Alias(aliasname : [list])
aliases1.save(flush:true)
def person = new Person(name : name, age : age, address : addobj, pets : [pet1], alias : [alias1, alias2], aliases : [aliases1])
person.save()
render person as JSON
}
}
Initially there are no persons in DB(which impliesPerson.findByAgeAndName(age,name) == null) Hence it creates a new object and saves it in database). So when I click on the url
> http://localhost:8080/TestJson/showPerson/sample/23
The output now is :
Now when I reclick on the same url (implies Person.findByAgeAndName(age,name) != null) Hence it gets from the database):
The output now is :
In database the address is saved as :
In database the person is saved as :
Can someone tell me how can I get the address (encircled in red) as not null and get the corresponding value when I try to get a saved object from database (i.e in this case kondapur and not null)
Grails JSON marshaller by default doesn't add nested classes, you have to add one line of code:
def showPerson(String name,String age){
JSON.use('deep')// <============================== Add this line
if(Person.findByAgeAndName(age,name) != null) {
render Person.findByAgeAndName(age,name) as JSON
}
else {
def addobj = new Address(address: "kondapur")
addobj.save(flush:true)
def pet1 = new Pet(name : "Dog", breed : "A")
pet1.save(flush:true)
def alias1 = "ALIAS1"
def alias2 = "ALIAS2"
def list = ["A"]
def aliases1 = new Alias(aliasname : [list])
aliases1.save(flush:true)
def person = new Person(name : name, age : age, address : addobj, pets : [pet1], alias : [alias1, alias2], aliases : [aliases1])
person.save()
render person as JSON
}
}

Grails clear hasMany entries and add new ones error?

I am currently working on a grails applications and I have a list of addresses that are attached to an account. Basically what I want to do is when the Account is edited is displays a current list of all the attached Addresses and then I can delete/add as many as I want from the view. When this data is captured it is picked up by the controller and what I want to do is to be able to clear all of the current Addresses from this account and then create the list again with what exists on the view, my code is below:
Account Domain:
class Account {
String name
Date dateCreated
Date lastUpdated
static hasMany = [addresses:Addresses]
static mapping = {
addresses cascade:"all-delete-orphan"
}
def getAddressesList() {
return LazyList.decorate(
addresses,
FactoryUtils.instantiateFactory(Addresses.class))
}
static constraints = {
name(blank:false, unique: true)
}
}
Address Domain:
class Addresses {
int indexVal
String firstLine
String postcode
String area
static belongsTo = [account:Account]
static mapping = {
}
static transients = [ 'deleted' ]
static constraints = {
indexVal(blank:false, min:0)
}
}
Account Controller:
def update() {
def accountInstance = Account.get(params.id)
if (!accountInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'account.label', default: 'Account'), params.id])
redirect(action: "list")
return
}
if (params.version) {
def version = params.version.toLong()
if (accountInstance.version > version) {
accountInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
[message(code: 'subscriptions.label', default: 'Subscriptions')] as Object[],
"Another user has updated this Account while you were editing")
render(view: "edit", model: [accountInstance: accountInstance])
return
}
}
accountInstance.properties = params
accountInstance.addresses.clear()
accountInstance.save(flush: true)
....
}
Error:
A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: com.tool.Account.addresses. Stacktrace follows:
Message: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: com.tool.Account.addresses
This error seems to be occurring in the controller on line:
accountInstance.save(flush: true)
I have tried several different way to get this to work and would really appreciate some help.
So it seems like you have done some work that Grails can do for you.
class Account {
String name
Date dateCreated
Date lastUpdated
List addresses
static hasMany = [addresses:Address]
static mapping = {
addresses cascade:"all-delete-orphan"
}
static constraints = {
name(blank:false, unique: true)
}
}
class Address {
String firstLine
String postcode
String area
static belongsTo = [account:Account]
}
This will produce the effect you want of having addresses being a list.
I've found either
instance.addresses = null
or
instance.addresses.clear()
to work for me
When you define addresses cascade:"all-delete-orphan" in Account class you don't need static belongsTo = [account:Account] in Addresses. So just try to remove that statement and test your code. See related link.

Equals object criteria query

If I have two domain classes like this:
class Company{
string Name
string address
}
class User {
string firstName
string lastName
Company company
}
How can I get all the users from company named Google using criteria query? Something like this:
def company = Company.findByName("Google")
def c = User.createCriteria()
def usersByCompany = c.list {
eq("company", company)
}
You can declare a block inside your closure to filter any field in the Company:
def usersOfGoogle = User.createCriteria().list() {
company {
eq('name', 'Google')
}
}
I just don't remember if it works only for relationships (belongsTo & hasMany), maybe you will need to change your domain class:
class User {
static belongsTo = [company : Company]
}

Why One-to-one relationship dosen't work?

I'm trying to create a very simple relationship between two objects. Can anybody explain me why I can't find the Company object via findBy method?
class Company {
String name
String desc
City city
static constraints = {
city(unique: true)
}
}
class City {
String name
static constraints = {
}
}
class BootStrap {
def init = { servletContext ->
new City(name: 'Tokyo').save()
new City(name: 'New York').save()
new Company(name: 'company', city: City.findByName('New York')).save()
def c = Company.findByName('company') // Why c=null????!
}
def destroy = {
}
}
A field called desc conflicts with the database keyword for descending sort. Per default a field is nullable:false in Grails. So first rename that field to for example description and then provide one or mark that field as nullable:true in your constraints.
class BootStrap {
def init = { servletContext ->
new City(name: 'Tokyo').save()
new City(name: 'New York').save()
new Company(name: 'company', city: City.findByName("New York")).save()
assert Company.findByName('company') != null
}
}
Remember that you can always check for the errors that prevent Grails from saving your objects to the database easily:
def invalidCompany = new Company() // missing required name property
if (!invalidCompany.validate())
invalidCompany.errors.each { println it }

Resources