Getting restful domain object without hasMany relationships - grails

We're writing an json API with grails. Here is a simplify example with the domains and controller:
class Employee {
String name
Section section
}
class Section {
static hasMany = [employees: Employee]
String name
}
#Transactional(readOnly = true)
class SectionController {
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
static responseFormats = ['json']
def index() {
request.withFormat {
json {
respond Section.list()
}
}
}
}
I want to get the Section list without employees, something like:
[
{"class":"Section","id":1,"name":"A"},
{"class":"Section","id":2,"name":"B"},
{"class":"Section","id":3,"name":"C"},
{"class":"Section","id":4,"name":"D"},
{"class":"Section","id":5,"name":"F"}
]
But the controller returns:
[
{"class":"Section","id":1,"name":"A","employees":[{"class":"Employee","id":1},{"class":"Employee","id":2},{"class":"Employee","id":3}]},
{"class":"Section","id":2,"name":"B","employees":[{"class":"Employee","id":4},{"class":"Employee","id":5},{"class":"Employee","id":6},{"class":"Employee","id":7}]},
{"class":"Section","id":3,"name":"C","employees":[{"class":"Employee","id":8},{"class":"Employee","id":9},{"class":"Employee","id":10}]},
{"class":"Section","id":4,"name":"D","employees":[{"class":"Employee","id":11}]}
]
When I delete the hasMany relationship, I get what I want, however, I need the relationship to do complex Criteria and hql queries
How can I do to return data without hasMany relationship.
Thanks.

Related

Grails: HIbernate-filter - Adding filter on mapped class column

I want to use grails hibernate filter plugin to add a filter on of my domain class.
http://grails.org/plugin/hibernate-filter
Domain classes:
class Movie {
String name
String genre
String yearOfRelease
boolean deleted
}
class EditRequest {
String reason
String requester
Date requestDate
String status //can be 'PENDING', 'ONHOLD', OR 'COMPLETE'
static belongsTo = [
movie: Movie,
requester: User
]
}
There could be multiple edit request for a movie.
I have an API where I need to display all edit requests for all non-deleted movies.
How do I add hibernateFilter for non-deleted movies in my EditRequest domain class
I tried below in my EditRequest class, but non of them works.
1.
static hibernateFilters = {
deletedMovieFilter(condition:'deleted=false', default:true)
deletedMovieFilter(collection:'movie', default: true)
}
2.
static hibernateFilters = {
deletedMovieFilter(condition: 'deleted = false')
deletedMovieFilter(collection: 'movie', joinTable: true)
}

Grails how to JSONify domain object including its nested domain classes?

I am trying to do one to many domain mapping in grails.Here are the two classes :
class TNDetails {
String tn
String tnpk
static hasMany = [iccid: ICCID]
static mapping = {
table 'ni_tn'
version false
tnpk column : 'TN_PK'
tn column: 'TN'
id column: 'TN_PK',name: 'tnpk'
}
}
class ICCID {
String sim
String customer
static belongsTo = [tn: TNDetails]
static mapping = {
table 'ni_sim'
version false
sim column: 'ICCID'
customer column: 'CUSTOMER'
tn column: 'TN_FK'
id column: 'SIM_PK'
}
}
The corresponding query can be written as : select TN,ICCID from ni_tn,ni_sim where ni_tn.TN_PK = ni_sim.RELATED_TN and tn_pk=1290.Now in my controller when i am fetch the details by passing tn_pk like this :
def index() {
def pk = params.tnPK
def details = TNDetails.findAll {
(tnpk == pk)
}
respond details
}
i get following result :
[
{
"class": "com.evolving.resource.tn.TNDetails",
"id": 1290,
"tnpk": "1290",
"iccid": [
{
"class": "com.evolving.resource.iccid.ICCID",
"id": 4209
}
],
"tn": "447400002035"
}
]
Now the problem here is it is not displaying the attributes sim and customer(from class ICCID).How do i display these two parameters also.What am i doing wrong here?
change your:
respond details
to:
JSON.use("deep") {
respond details as JSON
}
The Deep Converters fully render the associations (nested domainclass instances) and also handle circular relations (documentation)

Grails createCriteria on abstract domain

I am quite curious how one would use the criteria builder to access fields of an inherited class.
Let's assume we have the following class:
class A {
String fieldOne
String fieldTwo
static hasMany = [childs: AbstractChildClass]
}
and the abstract child class would look like this:
abstract class AbstractChildClass {
Integer valueOne
Integer valueTwo
A a
static mapping
tablePerHierarchy false
}
}
of course there are several extending classes such as:
class ExtendingClassOne extends AbstractChildClass {
DesiredObject desiredObject
static mapping = {
tablePerHierarchy false
}
}
let's also assume there is the class DesiredObject which looks like this:
class DesiredObject {
String infoA
String infoB
}
The question is how one would get the fields infoA and infoB by creating a criteria for class A. My approach so far is this:
A.createCriteria().list {
childs {
desiredObject {
ilike('infoA', '%something%')
}
}
}
This of course does not work because in the table ExtendingClassOne is only the id of the desiredObject and I have no clue how to join the object with the criteria builder to get its fields.
Thank you for reading.
Marco
don't expect 100% match between your domain model and the DB schema it's related to.
In your case the polymorphism would work only with tablePerHierarchy true for AbstractChildClass.
If you do want to stick with tablePerHierarchy false, you can define your class like:
class A {
static hasMany = [ childrenOne:ExtendingClassOne, childrenTwo:ExtendingClassTwo ]
}
thus your query would be as simple as:
A.withCriteria{
for( String c in [ 'childrenOne', 'childrenTwo' ] ){
"$c"{
desiredObject {
ilike('infoA', '%something%')
}
}
}
}

grails 2.4.0 domain modelling for REST

Working with grails 2.4.0 and RESTful controllers (JSON) and looking for guidance.
I have very simple domains (from a sample):
class Project {
String name
String description
static belongsTo = [owner : EndUser]
static constraints = {
name(blank: false, unique: true)
description()
}
}
class EndUser {
String userName
String fullName
String toString() {
"${fullName}"
}
static hasMany = [projects : Project]
static constraints = {
fullName()
userName(unique: true)
}
}
In ProjectController, I have kept html too for testing in addition to JSON.
class ProjectController extends RestfulController {
static responseFormats = ['html', 'json', 'xml']
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond Project.list(params), model:[projectInstanceCount: Project.count()]
}
def show(Project projectInstance) {
respond projectInstance
}
def listWithFullName(){
def a = Project.list(params)
a.owner.fullName
respond a
}
}
If go to html page: /project/show/1, I get html page with details:
HTML page:
Name: prj1
Description: prj desc
Owner: full name1
So far so good, if I do same with json (/project/show/1.json), I get:
{
class: "testapp.Project"
id: 1
description: "prj desc"
name: "prj1"
owner: {
class: "testapp.EndUser"
id: 2
}
}
As you see for "owner" field in JSON I am getting "id". How can I get fullname for owner in JSON. I thought I can do some thing like what I attempted in controller in method: listWithFullName() but that did not work. Any pointers? Thanks.

Grails criteria select when hasMany hasn't any elements

I have the classes:
class Course{
String name
static hasMany = [
studentGrades: StudentGrade
]
}
class StudentGrade{
String name
int grade
}
How can I make a criteria to get the courses without any student grade?
You could use the isEmpty criterion method:
def c = Course.createCriteria()
def results = c.list {
isEmpty("studentGrades")
}
See the docs for further informations.

Resources