Bidirectional One-To-One - grails

I have two domain classes:
class Contract {
String refNo
}
class Attachment {
byte[] data
String mimeType
String fileName
}
How can I set up the relationships so that I have both contractInstance.attachment and attachmentInstance.contract? I think this is bidirectional one-to-one but I'm not sure (one Contract has to have exactly one Attachment)...

class Contract {
Attachment attachment
}
class Attachment {
static belongsTo = [contract: Contract]
}
This define a 1-to-1 relationship between the two, with Contract being the owner of the relationship. This means that if you save/delete a Contract the save/delete will cascade to the Attachment, but the inverse is not true.

Wouldn't this work:
class Contract {
Attachment attachment
}
class Attachment {
Contract contract
}

Related

Grails Domain Class : hasOne, hasMany without belongsTo

I am new to Grails.
Can I use "hasOne" or "hasMany" without using "belongsTo" to another domain-class?
Thanks in advance.
Yes, you can. See examples in Grails doc: http://grails.org/doc/2.3.8/guide/GORM.html#manyToOneAndOneToOne
hasMany (without belongsTo) example from the doc:
A one-to-many relationship is when one class, example Author, has many
instances of another class, example Book. With Grails you define such
a relationship with the hasMany setting:
class Author {
static hasMany = [books: Book]
String name
}
class Book {
String title
}
In this case we have a unidirectional one-to-many. Grails will, by
default, map this kind of relationship with a join table.
hasOne (without belongsTo) example from the doc:
Example C
class Face {
static hasOne = [nose:Nose]
}
class Nose {
Face face
}
Note that using this property puts the foreign key on the inverse
table to the previous example, so in this case the foreign key column
is stored in the nose table inside a column called face_id. Also,
hasOne only works with bidirectional relationships.
Finally, it's a good idea to add a unique constraint on one side of
the one-to-one relationship:
class Face {
static hasOne = [nose:Nose]
static constraints = {
nose unique: true
}
}
class Nose {
Face face
}
Yes you can, but it behave differently
class Author {
static hasMany = [books: Book]
String name
}
class Book {
String title
}
In this case if you delete Author the books still existing and are independent.
class Author {
static hasMany = [books: Book]
String name
}
class Book {
String title
static belongsTo = [author: Author]
}
In this other case if you delete the Author it will delete all the books pf that author in cascade.
Many-to-one/one-to-one: saves and deletes cascade from the owner to the dependant (the class with the belongsTo).
One-to-many: saves always cascade from the one side to the many side, but if the many side has belongsTo, then deletes also cascade in that direction.
Many-to-many: only saves cascade from the "owner" to the "dependant", not deletes.
http://grails.org/doc/2.3.x/ref/Domain%20Classes/belongsTo.html
yes very easy like a class defintion but only specify hasMany but no need for hasOne
class Student {
String name
User userProfile
static hasMany =[files:File]
}
class User {
String uname
Student student
}
class File {
String path
Student student // specify the belongs to like this no belong to
}
Done!!

Grails mapping objects

I am new to grails and still trying to wrap my head around the mapping of objects. In our project we have three classes that are causing some problems Attendee, Vendor, and Person An attendee has one person and a vendor has many persons so we went with the following setup:
class Person{
String firstName
//Other details...
}
class Attendee {
Person person
}
class Vendor{
static hasMany = [
person:person
]
}
So the objects are being hydrated via a web form and I can confirm that the person details are being hydrated from a log statement. However we get the following error:
Message ORA-01400: cannot insert NULL into ("EIGHT_STATES_USER"."ATTENDEE"."PERSON_ID")
so we added static belongsTo = [attendee: Attendee, vendor: Vendor] to our Person based on a stackoverflow we read. But then when we tried to save the Attendee it wanted to create a Vendor.
Not sure where to go from here.
Try adding a mapping to your Attendee object:
Person person
static mapping = {
person cascade: "all"
}
More information about the custom mapping can be found here: http://grails.org/doc/2.3.x/guide/GORM.html#customCascadeBehaviour
The way you currently have it defined, you need to save the Person object first and then add it to the Attendee and save. You don't need the belongsTo in Person.
class Person {
String firstName
//Other details...
}
class Attendee {
Person person
}
class Vendor {
static hasMany = [
people:Person
]
}
def person = new Person(params)
if (person.save(flush:true)) {
def attendee = new Attendee(params)
attendee.person = person
attendee.save(flush:true)
}

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

Grails: How to define a domain property rendered on views but not persisted?

I have this domain classes, let's say:
class Person {
String name
Integer age
//car data that needs to be shown and filled in views
//but not persisted in Person class
String model
String color
static afterInsert = {
def car = new Car(model: model, color: color)
car.save()
}
}
class Car {
String model
String color
}
What I need is to show in my Person views (create and edit) the model and color properties that are defined inside Person class but these doesn't have to be persisted with this class. These data, model and color, have to be persisted using the Car domain class maybe using the afterInsert event. In other words, I need to save data from a domain class using the views from another domain class.
Thanks in advance.
You can use transients on properties you want GORM to ignore, for example
class Person {
static transients = ['model', 'color']
String name
Integer age
//car data that needs to be shown and filled in views
//but not persisted in Person class
String model
String color
..
}
Just curious but is there a reason you're not using associations
class Person {
..
static hasMany = [cars: Car]
}
class Car {
..
static belongsTo = [Person]
static hasMany = [drivers: Person]
}
.. or composition
class Person {
Car car
}
or simply data binding with multiple domains
//params passed to controller
/personCarController/save?person.name=John&age=30&car.model=honda&car.color=red
//in your controller
def person = new Person(params.person)
def car = new Car(params.car)

Grails: master domain field by detail domain field [hasMany]

There are domains:
class Order {
static hasMany = [execDepartments: Department]
String orderNo
//boolean signature
...
}
class Department {
String name
...
}
I want to add boolean signature field for Order but by Department, so I need field signature by execDepartments for Order. Is it possible? Please help.
Is this an m:m relationship?
why not create another domain like
class Order {
static hasMany = [execDepartments: DepartmentOrder]
String orderNo
//boolean signature
...
}
class DepartmentOrder{
boolean signature
Order order
Department department
}
class Department {
String name
static hasMany = [execOrders: DepartmentOrder]
}
Then you can write the belongTo
What you need is a list of signatures in the Order domain.
Possibly an OrderSignature domain that maps signatures to orders.

Resources