Grails 3 hasOne nullability issue - grails

While migrating an existing app from Grails 2.5 to 3.1, I ran into an odd issue with a bi-directional one-to-one relationship.
Imagine a simple model with a User and Employee objects. A User represents a generic user account. Not all users are Employees but all Employees are Users. Moreover Employees have references to managers, supervisors, etc (also User instances). User is the owning side of the relationship.
class User {
Employee employee
static mappedBy = [employee: "user"]
static hasOne = [employee: Employee]
static constraints = {
employee(nullable:true)
}
}
class Employee {
User user // represents employee's own account, a bi-directional one-to-one
User supervisor // represents a supervisor
static belongsTo = [user: User]
static constraints = {
user(unique:true)
supervisor(nullable:true)
}
}
The trouble after upgrading to Grails 3 is that in the create mode, this results in supervisor_id column of employee table being generated as NOT NULL, whereas in Grails 2 it was nullable as expected (with only user_id being NOT NULL).
I tested this with Grails 3.1.12 and 3.2.0, getting the same behavior with both. Am I doing anything stupid in my domain class declarations? I've tried multiple mappings to achieve the same behavior as in Grails 2.5 without luck. In some cases I'm even getting a foreign key on both sides of the relationship...

I don't know why your code was working with previous version of Grails, but it is wrong.
When you use hasMany and belongsTo, it is not necessary to define other property in the child object, and you don't need also to use the mappedBy property on the parent, and the same with the parent (property employee at User)
Grails doesn't need anything else to know which is the bidirectional property on both classes, and the constraint user(unique : true) neither.
So your classes should look like this:
class User {
static hasOne = [employee: Employee]
static constraints = {
employee(nullable: true)
}
}
class Employee {
User supervisor // represents a supervisor
static belongsTo = [user: User]
static constraints = {
supervisor(nullable:true)
}
}
It could be nice to know how is your DB structure. But in this way all foreign keys are stored in the employee table. But of course you could navigate from both entities. If you have different structure you could map your current database with this model. See this
employee.user
user.employee

Related

Grails - Mapping and Data Binding multiple collections of the same Domain Class

I have a domain class (let's call it security) and it needs three "one to many" relationships with another domain class (let's call it role). The three relationships are "current", "previous", and "new".
Basically I'm hoping to do something like this (in reality it's more complicated, but this will do to illustrate things):
class Security
{
static hasMany = [current: Role, previous: Role, new: Role]
Set current
Set previous
Set new
}
class Role
{
static belongsTo = [security: Security]
String name
}
Unfortunately something like this doesn't work since the Role domain class maps to only one table and that one table has only one column for the Security class' ID.
Is this possible without creating three separate Role classes and instead just map one class to multiple tables?
I'm also looking at the possibility of simply including a flag in the Role class to signal whether the role is current, previous, or new and only having one "one to many" relationship in the Security class. However, this approach is causing issues with data binding, since my HTML form would need to send two pieces of information for each role (the name property and also the type). Since these roles are listed in a HTML select statement I can only send one piece of information (the name).
If you do not depend on the belongsTo in Role (you have to remove it) you can use joinTable:
class Security {
static hasMany = [current: Role, previous: Role, next: Role]
static mapping = {
current joinTable: [name:'current']
previous joinTable: [name:'previous']
next joinTable: [name:'next']
}
}
You could use Grails mappedBy, just like below, if creating 3 fields inside the Role is not an issue:
class Security {
static hasMany = [current: Role, previous: Role, new: Role]
static mappedBy = [current: 'securityForCurrent',
previous: 'securityForPrevious', new: 'securityForNew']
}
class Role {
String name
Security securityForCurrent
Security securityForPrevious
Security securityForNew
}

Creating one-to-many & many-to-many for same domain class in grails

I want to create a domain class as like , One user can post many orders [Bidirectional] and one order can be liked by many users [unidirectional].
I have written a domain class as shown below ,
Class User {
String userName;
List orders
static hasMany = [Order]
}
Class Order {
String orderId
String orderName
//Indicates this order belongs to only one user
static belongsTo =[owner : User ] // Bidirectional
//Indicates order can be liked by many users
static hasMany = [likedUser : User] //Unidirectional
}
But I am getting am error saying invalid schema . Any body please help...
This post looks similar to my question but I am not getting , Please help.
First, order is a reserved word in SQL. Since GORM by default creates a table with the same name as your class, you'll need to either rename your class or provide a different name to use when mapping to SQL tables.
For example:
class Order {
static mapping = {
table 'user_order'
}
// ...
}
Another problem is that Order contains two associations to User. You need to tell GORM which one of these that is the bi-directional association from User to Order. That can be achieved using mappedBy, like this:
class User {
String userName
static hasMany = [orders: Order]
static mappedBy = [orders: 'owner']
}
Hope this helps.

How does one mix 'Reference' and 'No Reference' belongTo relationships in one Domain Class?

In Grails belongsTo allows one domain class to establish a cascading relationship with another domain class. There are two styles of relationships when using belongsTo: Reference and No Reference. Reference creates a property on the owned object while No Reference merely establishes an invisible GORM relationship.
Example parent domain-class:
class Car {
Engine engine
}
belongsTo without Reference property:
class Engine {
static belongsTo = Car
}
belongsTo with Reference property:
class Engine {
static belongsTo = [car:Car]
}
Not to hard right, however the trouble for me starts when we start using multiple belongsTo references:
belongsTo with multiple back references:
class Engine {
static belongsTo = [car:Car, user:User]
}
multiple belongsTo relationships without property references:
class Engine {
static belongsTo = [Car, User]
}
Here's the problem, how do I mix the two above styles?
Say I want a property reference for the User but not for the Car, how would I write that belongsTo call?
Any information on how to mix No Reference relationship links with Reference property in a single domain class would help.
Links:
Using Grails Object Relational Mapping (GORM)
belongsTo - grails.org
This question reposted by me on the official Grails forum
class Engine {
User user
static belongsTo = [Car, User]
}
That said, I always use the map (reference) syntax over the list (no reference) syntax because I like mine to be bi-directional.

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