GORM - Model Relationships Between Like Entities - grails

For my project I'm using Grails, but this is kind of a general ORM question.
I'm new to ORMs and ER diagrams, and trying to figure out how to best describe/implement the following:
I have 2 Entities: User, Connection
A Connection consists of 2 Users (and other primitive attributes). A user can be found in more than one Connection. How would you describe the relationship between User and Connection? I don't know what you would call it, 2 to many? How would you draw it in an ER diagram.
In GORM, should it be a bi-directional relationship?
Edit
As an added requirement, assume the users have specific roles in the relationship. Like student and teacher. So Connection would have student and teacher properties of type User.

the problem is not GORM, your problem deals with Entities. Before you code Domain classes, you have to image distinctly what info you would like to keep and operate. According your question and comments you prefer to use any RDBS. So let's to try to image easy simple tables (don't care about any ORM, Grails, bi\uni-directions) and try to fill this tables mock details.
Users
nickName (String)
otherUsersFields
Connection
teacher (Users)
student (Users)
otherConnectionFields
well, now we know all Users and all Connections. For given connection we can say who is teacher - connection.teacher and student - connection.student.
Note: any Connection has only two users.
pay attention to Users. Any User can be Student and Teacher. If User can be only Student or Teacher you will have to add additional field(s), for example
Users
nickName (String)
isTeacher (boolean)
otherUsersFields
now we have a list of user and know who is st. or tech.
How can I get all connections for given user?
GORM offers: Connection.findAllByStudent( givenUser), Connection.findAllByTeacher( givenUser)
Do this tables show your info completely?

I think what you want can be described as a many-to-many relationship, with some sort of constraint applied on Connection users collection. As for uni/bi-directional, I believe you can accomplish either depending on your use case - although uni-directional is probably harder to map/configure.
I haven't tested this, but a bi-directional many-to-many should look like this
class Connection {
...
Set users = [] //ensure users exists, constraints won't work on null
static belongsTo = [User]
static hasMany = [users: User]
static constraints = {
users maxSize: 2
}
}
class User {
...
static hasMany = [connections: Connection]
}
I don't have a uni-directional example off the top of my head, but I believe you may need to use an additional mapping class.
Again, I haven't tested this, but here's an example of uni-directional many-to-many with a mapping class
class Connection {
...
Set users = []
static hasMany = [users: ConnectionUser]
static constraints = {
users maxSize: 2
}
}
class User {
...
}
class ConnectionUser {
User user
Connection connection
//or for cascading effects
//static belongsTo = [connection: Connection]
...
... //lots of additional code to manage adding,
... //removing, updating Connection-to-User relationships
}
Connection knows about Users, but Users do not know about Connections they belong to. If you go the mapping class route, you'll need to manage the Connection to User relationships manually. Take a look at Spring Security Core PersonAuthority class for an example of mapping class.

Related

Grails 3 hasOne nullability issue

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

How to define association relationship in grails

UPDATED
I have a domain classes as below
class Training{
// has one createdBy object references User domain and
// has one course object references Course domain
// has One Trainer1 and Trainer2 objects refernces Trainer Object.
}
class Trainer{
String name
//can have many trainings.
//If Trainer gets deleted, the trainings of him must be deleted
}
Class User{
String name
// can have many trainings.
}
class Course{
String name
//If Course gets deleted, Trainings of this course must be deleted
// can have many trainings.
}
I have got a training create page, Where I have to populate already saved Course, User, Trainer1 and Trainer2. I am not saving them while Creating the training.
So, How to specify the relationship in grails
You did not put any effort to searching answer for yourslef. There are plenty basic examples and blog posts how to map relations in Grails. You should start with Grails documentation of GORM - Grails' object relational mapping. You can find it here.
I see some minor flaws in yout initial design: ie why should training be deleted if user is deleted when trainings will obviously tie with many users. Can training exists without trainers or vice versa ?
I would start with something like this:
Class Training {
static hasMany = [users: User, trainers: Trainer]
static belongsTo = Course
}
Class Trainer {
String name
}
Class User {
String name
}
Class Course {
String name
static hasMany = [trainings: Training]
}
EDIT: I have to agree with Tomasz, you have jumped here too early without searching for answers yourself. Grails.org has good documentation about GORM with examples too.

One-to-many and many-to-many relationship between two classes? (Grails ORM)

I'm having an issue dealing with two entities which should have a relationship of one to many and many to many. Let me show you the case: there are users, which create and take part of activities. So an activity could have several users and just one activity creator, meanwhile an user can create and belong to many activities.
So I did something like this:
class User {
static hasMany = [activities:Activity, activitiesCreated: Activity]
static mappedBy = [activitiesCreated: "creator"]
...
}
class Activity{
static hasMany = [users:User]
static belongsTo = [users:User]
Usuario creator
...
}
This raises a runtime exception, which is this one:
No owner defined between domain classes [class User] and [class Activity] in a many-to-many relationship. Example: static belongsTo = Activity
The many-to-many relationship works fine if I don't try to implement the one-to-many, so it wouldn't be the problem.
And this is where I'm stuck :/
I would have third entity to realize the many to many relationship. For example, let say represent actual execution of the Activities as an Event, which means a Event has one ore more Activities, time stamp/time frame, and one ore more participating Users. A user can create one ore more activity and by the same token the owners of Activity will be considered to own the Event.

Removing child-parent association in GORM

Consider the following domain classes
class Business{
static hasMany = [contacts:ContactPerson]
}
class ContactPerson{
}
Given the following domain classes, say we use the following examples:
Alice is ACME's contact person. Bob and Carol are Calamity Corp's contact person.
Say I wanted to remove Bob in the ContactPerson table. Thus:
bob.delete(flush:true)
But the code will result to the server complaining about contraints:
ERROR: update or delete on table "contact_person" violates foreign key constraint
"fk4a69c6b329ef2fe1" on table "business_contact_person"
Detail: Key (id)=(174) is still referenced from table "business_contact_person".
In this context, the exception is thrown because Bob is still associated with Calamity Corp.
How do I delete Bob from the ContactPerson table? I wanted to remove Bob from the database altogether. I don't want to add belongsTo since I don't want to cascade the delete to Business' children (that is to say, if I delete Acme Corp from the database, I still want Alice to be in the system).
I've seen examples on disassociating the parent from the child but not the other way around.
I believe by simply adding a belongsTo, the cascade should work as expected...
class Business{
static hasMany = [ contacts:ContactPerson ]
}
class ContactPerson{
static belongsTo = [ business: Business ]
}
Ok. So with a little more digging, I finally got the codes that I wanted. John Rellis' post on Relationship Advice : Grails One-To-Many was especially helpful. In this article, he mentions how to query from children to parent (which is exactly what I am looking for).
Going back to the question, I wanted to remove Bob from the ContactPerson table but given the relationship between Business and ContactPerson simply calling bob.delete() simply would not do. What I need is to look for all businesses associated with Bob and remove the association. Thus the code below:
def bob = ContactPerson.get(params.id)
def criteria = Business.createCriteria()
def businesses = criteria.listDistinct{
createAlias("contactPersons","c")
eq("c.id", bob.id)
}
businesses.each{business->
business.removeFromContactPersons(bob)
business.save(flush:true)
}
bob.delete(flush:true)
I also added a new mapping to the Business domain model:
static mapping = {
children cascade:"all-delete-orphan"
}

Need ideas in designing Domain classes Grails

I am learning Grails, I am trying to build a small application. And for now I am working on the registration part.
There are 3 different views for registration process
1) As an employee my registration view is different with different fields
2) As an employer registration view would be different where I would be collecting company details, an authorized representative who can act on behalf of the company. So as a matter of fact I was thinking that company(employer) is not the actor but representative is an actor and hence need a representative domain class.
3) retailer registration view is different.
So I need to define the domain classes and its relationships I am very much new to grails and I need some guidance in designing
I was initially thinking of User domain class and have UserTypes(which defines different types of users ex. representative,retailer and employee) but not sure if that works.
Appreciate if someone could help me in building my domain classes.
Thanks
You definitely want to map out your domain classes before you start working on the views. Is the authorized rep always going to be an employee, or is it a completely different entity?
Think of it in terms of objects, and try to mimic it as much as possible. A company has employees, and can have an authorized representative. Here's a sample mock up:
class Employee {
String firstName, lastName /* etc... */
}
class Company {
String name /* etc */
Representative authorizedRepresentative
static hasMany = [ employees : Employee ]
}
class Representative {
}
Of course, you may want to have references from the Employees back to its Company. Have a look at the Object Relational Mapping portion of the Grails docs.

Resources