Grails Rest controllers and foreign keys - grails

I have created two domain class named City and Address in Grails 3:
class City {
Long id
static hasMany = [addresses: Address]
static mapping = {
id generator: "increment"
}
}
class Address {
Long id
}
I have created two controllers for these classes. The controllers just extend the RestfulController class. I have created the following URL mapping:
group("/api") {
"/city"(resources: 'city') {
"/addresses"(controller: 'address')
}
"/address"(resources: 'address')
}
The idea being that I can access the addresses belonging to a city (with id = 1) via localhost:8080/api/city/1/addresses. Unfortunately, I always get all addresses and not only the ones belonging to the given City. If I break on the index method of the AddressController I see that the params given to the method indclude a cityId which contains the id of the City passed in the query. However, it seems that the id is not picked up during the database query. Am I doing something wrong here? Do I need to add a belongsTo / mappedBy or a City to the Address?

Related

how not to load hasMany entities from database using Grails

I've got 3 classes:
class Author {
static hasMany = [books: Book]
static belongsTo = [company: Company]
String name
}
class Book {
static mapping = {
collection "documents"
id generator: 'assigned',index: true, indexAttributes:[background:true, unique:true, dropDups:true]
}
String id
String name
}
class Company {
static mapping = {
collection "documents"
id generator: 'assigned',index: true, indexAttributes:[background:true, unique:true, dropDups:true]
}
String id
String name
}
I want to use
Author author = Author.getByCompanyAndBook(1,1);
but when running this Grails retrieves all the Book objects from the database.
I need those Books only as identifiers for the Author and I am not going to use those objects.
Is there a way for me to force Grails not to fetch the Books and Companies from the database?
I tried to use:
static mapping = {
books lazy: true
}
but still all of the Books and the Company were loaded.
Edit:
I am using mongo db as my database.
That's weird - collections are lazy by default, so getting an author shouldn't retrieve anything in the books collection until you access the books property. But regardless, even if it worked as expected I recommend that you avoid mapped collections. See this talk which shows why collections are unnecessarily expensive and provides workarounds to minimize the costs.

Groovy/Grails many-to-many delete relation

I have 2 domain class with a many to many relationship. When I delete the entity that belongs to the other, I have to remove the relation before in order to avoid a foreign key error. These relations are connected via the third class, third table in MySQL.
class City {
String nameCity
static hasMany = [visits:Visit]
/* FIRST VARIANT. REMOVES ONE VISIT ONLY */
def beforeDelete() {
Visit.withNewSession {
def visitList = Visit.findByCity(this)
visitList.each { it.delete(flush: true) }
}
}
}
//_____________________________________________
class Visit { // it is the relation class
City city
Person person
}
//_____________________________________________
class Person {
String namePerson
static hasMany = [visits:Visit]
}
So when I delete the relation between two classes, it removes one relation only. I mean, if we have 1 City and 1 Person, and try to delete this City, the app functions OK. But if you have more than one Person attached to the City, we will have:
"Cannot delete or update a parent row: a foreign key constraint fails". But one relation is deleted.
If I try to delete the City one more time, the second Person will be deleted. My app behaves like that until the last Person to be deleted. So, beforeDelete() method works great.
My problem is I don't understand how to create a collection of relations and remove them all in a cycle (loop). If I make like this:
class City {
String nameCity
static hasMany = [visits:Visit]
/* SECOND VARIANT. TYPE CAST EXCEPTION */
Collection<Visit> visitList() {
Visit.findByCity(this)
}
def beforeDelete() {
Visit.withNewSession {
visitList().each { it.delete(flush: true) }
}
}
}
I have org.codehaus.groovy.runtime.typehandling.GroovyCastException 'Cannot cast object 'mypackage.Visit : 1' with class 'mypackage.Visit' to class 'java.util.Collection'.
Any thoughts and help highly appreciated.
Have you tried the following? In theory should work...
class City {
String nameCity
static hasMany = [visits:Visit]
class Visit { // it is the relation class
City city
Person person
static belongsTo = [city:City, person:Person]
}
class Person {
String namePerson
static hasMany = [visits:Visit]
}
And just make a normal delete. In this way, if you delete a City or a Person, all its related visits will be deleted

Many to many relationship in grails and status of each record

I have 2 domain models having many to many relation with themselves
Candidate{
String name
static hasMany = [positions:Position]
}
Position{
static hasMany = [candidates:Candidate]
static belongsTo = [Candidate]
}
my requirement is to fetch the shortlisted status of each candidate for each position, but grails create the intermediate table itself so any idea how to implement it.
Any comments,ideas,examples will appreciated.
If the status is to be stored on the relationship you could create a mapping domain class for the relationship like described in this answer.
The statuses could then be retrieved by (assuming a CandidatePosition class name):
def candidatePositionList = CandidatePosition.findAllByCandidate(candidateInstance)
candidatePositionList.each {
it.position.name // Position name
it.status // Status of candidate for Position
}

Grails hasMany error creating beans

I'm creating a (theoretically) simple hasMany relationship within a domain class. I have two tables with a foreign key relationship between the two. Table 1's domain object is as follows:
Functionality{
String id
static hasMany = [functionalityControllers:FunctionalityController]
static mapping =
{
table 'schema.functionality'
id column:'FUNCTIONALITY_NAME', type:'string', generator:'assigned'
version false
}
}
and domain object 2
FunctionalityController
{
String id
String functionalityName
String controllerName
static mapping =
{
table 'schema.functionality_controller'
id column:'id', type:'string', generator:'assigned'
version:false
}
}
The issue I am having is that when I have the hasMany line inside of the Functionality domain object, the app won't start (both the app and the integration tests). The error is org.springframework.beans.factory.BeanCreationException leading to Invocation of init method failed; nested exception is java.lang.NullPointerException.
Any help would be appreciated.
UPDATE:
*Working Domains*:
class Functionality {
String id
static hasMany = [functionalityConts:FunctionalityCont]
static mapping =
{
table 'schema.functionality'
id column:'FUNCTIONALITY_NAME', type: 'string', generator: 'assigned'
functionalityConts( column:'functionality_name')
version false;
}
}
and
class FunctionalityCont {
String id
String functionalityName
String controllerName
static belongsTo = [functionality: Functionality]
static contraints = {
}
static mapping =
{
table 'schema.functionality_controller'
id column:'id', type: 'string', generator: 'assigned'
functionality(column:'FUNCTIONALITY_NAME')
version false;
}
}
Well 2 things...
1.I'm not sure but I guess that your domain class with the prefix 'Controller' maybe is the responsible, this is because grails is convention over configuration and by convention the controller class ends with Controller prefix and are in the controller folder, in this case is a lil' confusing
2.In GORM and in this case the relationship between objects can be unidirectional or bidirectional, is your decision to choose one, but in both cases there are different implementations, the class Functionality(btw is missing the 'class' word) has the right relationship to FunctionalityController through hasMany, but FunctionalityController doesn't knows about the relationship, so you can implement:
// For unidirectional
static belongsTo = Functionality
// For bidirectional
static belongsTo = [functionality:Functionality]
// Or put an instance of Functionality in your domain class,
// not common, and you manage the relationship
Functionality functionality
So check it out and tell us pls...
Regards
Try adding
static belongsTo = [functionality: Functionality]
to your FunctionalityController class. I suspect there is more to your error than what you've shown, but generally a hasMany needs an owning side to it. Since that is where the foreign key actually lives.

Grails - How to implement a foreign key relationship not using an id column?

Have been trying to look for an answer for hours, but have so far not managed to come up with an adequate solution, so I'm hoping someone here might have some more experience with Grails, and implementing custom relationships in it.
My problem is that I have two classes:
Company
OrderConfig
OrderConfig contains two references to Company. 1 for a consignee, 1 for a shipper. I implemented the relationship (see below), and everything looks dandy, with my order_config table containing both a consignee_company_id column and a shipper_company_id column.
However, I do not want or need a company_id column at all. I would prefer using the CompanyName as the identifying column. How can I prevent Grails from automatically adding the id column to the company table, and instead use the companyName column as the primary key, thus ensuring my order_config table will be generated containing the companyName and not the company_id?
I tried embedding the company in the orderconfig class, and wrestled with all kinds of other options including the mappings, however I ran into trouble with each and every one of them.
Thanks in advance!
My code so far:
class OrderConfig {
static hasMany = [consignee:Company, shipper:Company]
String toString() {
return "${consignee}"
}
static constraints = {
consignee (blank:false, maxSize:10)
shipper (blank:false, maxSize:10)
}
Company consignee
Company shipper
}
class Company {
String toString() {
return "${companyName}"
}
static constraints = {
companyName(blank:false, maxSize:10)
companyAddress1(blank:false, maxSize:40)
companyAddress2(blank:false, maxSize:40)
companyAddress3(blank:false, maxSize:40)
companyAddress4(blank:false, maxSize:40)
companyZipCode(blank:false, maxSize:36)
companyCountry(blank:false, maxSize:36)
}
String companyName
String companyAddress1
String companyAddress2
String companyAddress3
String companyAddress4
String companyZipCode
String companyCountry
}
You need to look at the advanced GORM config options in the documentation, in section 5.5.2.1
There is an example
class Person {
String firstName
static hasMany = [addresses:Address]
static mapping = {
table 'people'
firstName column:'First_Name'
addresses joinTable:[name:'Person_Addresses', key:'Person_Id', column:'Address_Id']
}
}
there you can see how they are specifying the key and column name on which to do the stuff.
Edit -- I reread your question: if you are asking how to change it so Company has an assigned id, you might be able to do something like this example
static mapping = {
id generator:'assigned', column:'column_name',name:'propertyName'
}
where more options are available here: http://www.grails.org/doc/1.3.x/ref/Database%20Mapping/id.html

Resources