hasMany mapping table not created - grails

I am having a GORM issue.
I try to map one domain Object with another with hasMany.
class PrototypePriceModifierCode {
...
static hasMany = [activitys:Activity]
...
}
Since I don't need a back reference in Class Activity I don't have any reference to PrototypePriceModifierCode.
Having only this creates my mapping table as expected (1).
prototype_price_Modifier_code_id activity_id
In the Activity, I need a reference to a PrototypePriceModifier, which has nothing to do with the above mapping table.
The problem is that the mapping table is not generated anymore as soon as I define
class Activity{
...
PrototypePriceModifierCode prototypePriceModifierCodeAttached
How can I get the mapping table created and having a reference to PrototypePriceModifierCode in my Activity domain class?

Try like this:
class Activity {
static belongsTo = [PrototypePriceModifierCode]
}
This way, there will be a column in the activity table for PrototypePriceModifierCode instead of creating a separate table for hasMany.

When Activity does not have the prototypePriceModifierCodeAttached property, the hasMany in PrototypePriceModifierCode results in a uni-directional one-to-many association. In the database, this is implemented with a mapping table.
However, when Activity has the prototypePriceModifierCodeAttached property the association changes to a bi-directional one-to-many. In the database this means the activity table has a foreign key pointing to it's prototype_price_modifierCode, so the mapping table is not used. You can read more about these differences here.
"prototypePriceModifierCodeAttached" property
If you want a uni-directional one-to-many and the property Activity.prototypePriceModifierCodeAttached, you can create a getter method which looks up the PrototypePriceModifierCode:
class Activity {
PrototypePriceModifierCode getPrototypePriceModifierCodeAttached() {
PrototypePriceModifierCode.where {
activitys.id == this.id
}.get()
}
}
The downside here is that the property is inaccessible to GORM; can't query on it.
"price_modifier_code_id" column
On the other hand, if what you want is a price_modifier_code_id column in the activity table, you can add it as a long:
class Activity {
long prototypePriceModifierCodeAttached
static mapping = {
prototypePriceModifierCodeAttached column: 'price_modifier_code_id'
}
}
This makes it possible to use GORM queries on the property, but only on the PrototypePriceModifiedCode ID, not the domain class instance itself.
A combo
You can combine both approaches, as long as you're willing to do a bit of maintenance:
class Activity {
long priceModifierCodeId // <--- You gotta maintain this property manually.
PrototypePriceModifierCode getPrototypePriceModifierCodeAttached() {
PrototypePriceModifierCode.get(priceModifierCodeId)
}
}
Note: activitys is misspelled. It should be activities.

I ended up using String saving comma separated ids.
String activitys
this.activitys.split(',')each{
p.activitys.add(Activity.get(Long.parseLong(it)))
}
As I don't need referencial integrity here this works fine for me.

Related

Grails how to allow orphan of many to one

Can grails allow a many relationship to be orphaned with domain class instructions?
i.e. When I delete a related one relationship the corresponding column on the many is set to NULL.
the one
class TrackingNumber{
static hasMany=[records:AttendanceRecords]
}
the many
class AttendanceRecord{
static belongsTo=[site:Site, number:TrackingNumber]
static constraints={
number(nullable:true)
}
}
It seems deleting TrackingNumber instance tries to delete all of the Attendance records as well, which is undesired. I'd rather not have to removeFrom() each association in the controller.
It seems deleting TrackingNumber instance tries to delete all of the
Attendance records as well, which is undesired.
The belongsTo is causing the deletes to cascade.
Instead of this...
class AttendanceRecord{
static belongsTo=[site:Site, number:TrackingNumber]
static constraints={
number(nullable:true)
}
}
You can do this...
class AttendanceRecord{
static belongsTo=[site:Site]
}

Unidirectional Many To One mapping with cascade

Is it possible to map the following with GORM?
I want to get rid off all associated events when I delete a person.
Person object should not have a link to events.( I want to avoid using hasMany on Person domain)
class Person {
String username
}
class Event {
String description
static belongsTo = [person:Person]
}
I'm getting now a 'Referential integrity constraint violation' when doing person.delete() because events are not removed before deleting person.
I don't think that is possible without using hasMany (speaking of which, why do you want to avoid that anyway?)
This SO Question states:
Hibernate only cascades along the defined associations. If A knows
nothing about Bs, nothing you do with A will affect Bs.
Use static hasMany and bam, problem fixed.
Edit:
The only way I think you could achieve this is using beforeDelete on the Person class to delete all the associated Events, i.e.
class Person {
def beforeDelete() {
def events = Event.findAllByPerson(this)
for (e in events) {
e.delete()
}
}
}
See the documentation on Events and Auto Timestamping for more info on that.
The above will not work
Why not define a no reference mapping:
class Person {
String username
static hasMany=[Events]
}
This way there is no actual bindings of events to person but a person can have many events

Child class object can not delete

I have some domain class Incident,Problem, Category, Impact, Urgency etc.
Class Incident
{
Category category
String subject
Impact impact
}
Class Problem
{
Urgency urgency
Category category
String title
}
Class Category
{
String categoryName
String description
}
now, some rows are inserted into this class. now if I am deleting category it throws error like 'grails cannot delete or update a parent row'..
so what I have to do for deleting?
The problem is - you have reference to Category in Incident and Problem classes, so database tables for those classes will have Foreign key on category table, so you can not delete a category untill you either remove those incidents/problems or update those incidents problems and set category to null (you will have to make them as nullable in domain constraints)
So either you do
Problem.executeUpdate('update Problem p set category = null where category = ?', [category])
Same for incidents
Or you can model your domain classes using belongsTo and hasMany and grails will handle every thing automatically
Some thing like
class Problem {
static belongsTo = [category:Category]
}
class Category {
static hasMany = [
problems: Problem
]
static mappings = {
problems cascade: "all-delete-orphan"
}
}
I would prefer to manage relationships using belongsTo, hasMany, hasOne rather then just using references, it expresses the model better.
It depends on your domain model as well, in your business can problems, incidents exist without a category ! or they must belong to some category. If your answer is first option, your dont want to cascade delete, but update those incidents/problems with null category, if your answer is second option - you needs cascade all-delete-orphan
How your Category looks like, is it belongsTo Incident domain class,if category belongs to some domain class you can not delete it.
Ref : See here

Grails many-to-many relationship across the same table

I'm using Grails and I want to have a unidirectional many-to-many relationship.
In my application, an Employee can "bookmark" another Employee in order to quickly access them to leave notes. Employees need not know who has bookmarked them.
In other words, I essentially want to have an employee.bookmarks property that I can use for this.
Thus far, I've found the documentation on many-to-many relationships for Grails ORM, but this seems to be exclusively across two different tables.
Sounds like you just need a regular unidirectional 1-many:
class Employee {
...
static hasMany = [bookmarks: Employee]
}
You can use transient properties and an additional table "Bookmark" to do this task:
class Employee {
String name
static transients = ["bookmarks"]
def getBookmarks() {
Bookmark.findAllByBookmarker(this, [sort: "id", order: "asc"])
}
...
}
class Bookmark implements Serializable {
Employee bookmarker // the employee who bookmark someone
Employee bookmarkee // the employee who is bookmarked
static mapping = {
table "Bookmark"
id composite: ['bookmarker', 'bookmarkee']
bookmarker(column: "BOOKMARKER_ID")
bookmarkee(column: "BOOKMARKEE_ID")
version false
}
static Bookmarker get(long bookmarkerId, long bookmarkeeId) {
find 'from Bookmark where bookmarker.id=:bookmarkerId and bookmarkee.id=:bookmarkeeId',
[bookmarkerId: bookmarkerId, bookmarkeeId: bookmarkeeId]
}
...
}
This method uses table "Bookmark" to store the relations between employees, so it is possible to have 2 people bookmark the same employee. Note that class Bookmark must implements Serializable.

Grails/GORM: The meaning of belongsTo in 1:N relationships

In an ordinary one-to-many mapping the "one"-side is the owner of the association. Why would anyone use the belongsTo-mapping for such a mapping? Am I missing some side-effect of specifying belongsTo?
In other words: what are the effects of specifying a belongsTo-mapping in GORM vs. not specifying it?
Whether to specify belongsTo depends upon the type of referential action you want.
If you want Grails to do On Delete, CASCADE referential action, then DO specify belongsTo. If you want Grails to do On Delete, RESTRICT referential action, then DON'T specify belongsTo.
e.g.
// "belongsTo" makes sense for me here.
class Country {
String name
static hasMany = [states:State]
}
class State {
String name;
// I want all states to be deleted when a country is deleted.
static belongsTo = Country
}
// Another example, belongsTo doesn't make sense here
class Team {
String name
static hasMany = [players:Player]
}
class Player {
String name
// I want that a team should not be allowed to be deleted if it has any players, so no "belongsTo" here.
}
Hope this helps.
Specifying belongsTo allows Grails to transparently cascade updates, saves and deletes to the object's children. Without belongsTo, if you attempt to delete a master record, you'll end up getting a foreign key violation if it has any details it owns.

Resources