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

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)

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)
}

How to retrieve list with max, offset and sort parameters with Grails ORM

I have a grails application with User and Group domain objects. The User has many Group objects and the Group object contains many User objects:
class User implements Serializable {
static constraints = {
usergroups nullable: true
}
static mapping = {
usergroups cascade: 'all-delete-orphan'
}
static hasMany = [
usergroups: Group
]
static mappedBy = [
usergroups : "creator"
]
}
class Group {
static belongsTo = [
creator : User
]
static hasMany = [
members : User
]
static constraints = {
creator nullable: false
members nullable: true, maxSize: 100
}
}
Given a Group object, can I retrieve the members with max, offset and sortBy parameters? Something like...
def members = User.where {
/* how to specify only the users in 'group.members'? */
}.list(
max: max,
offset: offset,
sortBy : sortBy
);
Edit
To try and fix the problem I have altered the User class to contain a joinedgroups field...
class User implements Serializable {
static constraints = {
usergroups nullable: true
joinedgroups nullable: true
}
static mapping = {
usergroups cascade: 'all-delete-orphan'
}
static hasMany = [
usergroups: Group
joinedgroups: Group
]
static mappedBy = [
usergroups : "creator",
joinedgroups : "creator" // if I don't add this Grails complains there is no owner defined between domain classes User and Group.
]
}
But now when I try to retrieve all the User's usergroup objects in another part of my application only a single usergroup is returned...
def groups = Group.where {
creator.id == user.id
}.list(max: max, offset: offset, sort: sortBy); // should return 3 groups but now only returns 1
This query worked before so maybe adding the extra mappedby entry in User has caused the problem. Is the new mappedby field in User incorrect?
If all the groups that contains a user are saved in the usergroups field, you could use:
def query = User.where {
usergroups { id == myGroup.id }
}
def users = query.list(max: 10, offset: 0, sort : "id")

Getting restful domain object without hasMany relationships

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.

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%')
}
}
}
}

How to limit the size of association in grails?

I have a grails domain class as below :
class Order {
String orderId = 'OD' + System.nanoTime().toString()
Date orderedDate
String itemName
List bids;
static hasMany = [ bids: Bid ;likedUsers: User,]
static belongsTo =[owner:User]
}
class Bid {
Integer amount
User bidedUser
static belongsTo = [Order]
}
class User {
String username
String password
String emailId
List orders
static hasMany = [orders:Order]
}
What I am trying to do is , to query for an order with bits with maxResult of 10 as like
def critObj = Order.createCriteria()
critObj.list{
eq("id" ,1)
bids {
maxResult(10) //Trying to fetch only 10 records
}
}
How can I load only 10 bits(associations) , is it possible? . Or My design of domain class is wrong?
I think this should work:
def results = Bid.withCriteria {
order {
eq 'id', 1
}
projections {
property 'order'
}
maxResults 10
}
But please note that you have to change your Bid domain class to add the relation in the other way from Bid to Order:
class Bid {
...
static belongsTo = [order: Order]
}

Resources