I've two domain classes which are bonded with a bidirectional one-to-one relationship to each other, this being implemented using hasOne.
class AssessmentData {
static hasOne = [assessmentField:AssessmentField, assessment:Assessment]
AssessmentField field
}
class Assessment {
AssessmentData assessmentData
}
But I'm quite a bit confused about the way Grails implements this relationship at the database level. As described here, it simply sets the foreign key at the child domain class only, in my case, to the Assessment and AssessmentField tables. Its my primitive instinct that both tables should have a foreign key referring to each other in order to establish a one-to-one bidirectional relationship. But since this is not the case, I wanna know how this is achieved by Grails.
Its my primitive instinct that both tables should have a foreign key referring to each other in order to establish a one-to-one bidirectional relationship
Your instincts have failed you. The domain described in your question will generate these 2 database tables:
assessment_data
----------------
id
assessment
----------------
id
assessment_data_id
Using SQL we can get the assessment associated with an assessment_data with id 4
select * from assessment where assessment_data_id = 4
We can also go the other way and get the assessment_data associated with an assessment with id 5 using
select ad.* from assessment_data ad
inner join assessment a ON a.assessment_data_id = ad.id
where a.id = 5
So if we can "go both ways" in SQL, then we can do it with HQL, criteria queries, dynamic finders, etc. because these all ultimately get translated to SQL.
Related
I will preface it by saying I'm a database person, moving into .NET, MVC, EF etc. So I fully understand about joins and foreign keys and so on but I am struggling with the EF side.
I worked through a tutorial where we did the following:
create a Student table (StudentID and personal details), a Course table (CourseID and subject details), and an Enrollment table (EnrollmentID, student and course IDs and the grade given to that student for that class).
create Models, Controllers and Views for Student and Enrollment entities to allow editing the name of a Student, enrolling a student for a class and giving them a grade, list out all enrollments, etc.
In that tutorial the Enrollments table is (what I know as) a "bridge" table because student to class is a many-to-many relationship.
So do I only need this "intermediate" model/view/controller if it's a many-to-many scenario like this?
The actual structure I want to program is:
Article (ArticleID, title, author, summary, content...) is a member of a
Category (CategoryID, title, description, ...)
Then I want to have a drop down list (or whatever UI element) of Categories of which clicking on the selected Category will give a page with a table of Title/Author/Summary of the articles that go in that category.
If an Article can be in more than one category ("Effective Use of Catnip" could be under both "Playing Games with Cats" and "Life Hacks") is that where I would need a 'bridge' table?
Please can someone explain in simple terms - whether I am just being put off by the "many to many" nature of the data in that tutorial, or if the 'bridge' table structure is more fundamental to EF for navigating a PK/FK relationship.
I think the tutorial you are reading is trying to introduce you to the basic concepts of EF. If you have a many-to-many relationship, on database side you will always have three tables:
Student
Course
Enrollment (Student_Id, Course_Id)
On EF world, you can represent those three tables as three different entities. However, if you want to have a more "natural" way of representing the relation between Students and Courses, EF allows you to declare many-to-many as two lists:
public class Student {
... properties
virtual List<Course> Courses;
}
public class Course {
... properties
virtual List<Student> Students;
}
However, you need to instruct EF how this references on both side needs to be treated. For that, you can use fluent API. With this fluent API you can define the table name that references both tables/entities:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>()
.HasMany<Course>(s => s.Courses)
.WithMany(c => c.Students)
.Map(cs =>
{
cs.MapLeftKey("StudentRefId");
cs.MapRightKey("CourseRefId");
cs.ToTable("StudentCourse");
});
}
Check this article explaining the M:N relationship using fluent library API. Is really simple, and with that you don't need this additional element on the middle.
In terms of UI, you just need to select the list of courses the student want to take, or the list of students the course has to have. Is up to you how you want to present the information to the user, as both functionalities (students taking courses and courses defining its students) point to the same m:n relation.
I think a simple way can be to show a </select> list with the students, and then show the list of courses he can apply to.
The project you want to create uses the same ideas. Basically, with EF you will always need to think in terms of "tables". It is true that EF allows you to abstract your tables to entities, but still you need to follow some rules. To sum up: you are right. The "bridge" table is where you need to store the many-to-many relationships.
If I have the following unidirectional one to many relationship between two domain classes:
class Single {
static hasMany = [ multiples: Multiple ]
}
class Multiple {
...
}
Is there a way to cascade the delete from the Multiple class to the many relationship on Single?
What I have found that works is to add to add an onDelete: Cascade property to the FK that exists on the multiple_id column of the join table via the database script - however what I would really like to do is to express this in the GORM mapping DSL (and without creating a separate domain class to explicitly represent the join table). But there does not appear to be a way to manage relationships on the implicit join table of a uni one-to-many - unless I've missed something.
Is there a reason not to use bidirectional? If not, take a look at http://grails.org/doc/2.4.x/ref/Domain%20Classes/belongsTo.html?
I have 2 entities in my domain that have a one-to-one relationship with one another.
Entity Business has a Promotion. And Promotion has a Business. I know this doesn't make a lot of sense and I could as well integrate the fields of Promotion into my Business entity, but I'm dealing with a legacy database here and I'm trying to model my domain on top of it without changing anything in the database for now.
My problem is that although the relationship goes both ways, it's only stored on the side of the promotion table that has a business_id foreign key, but there is no promotion_id foreign key in the business table. So when I try to run my app, Grails can't find the promotion_id column it expects to find for the promotion field in Business.
Is there any way to model my domain entity so that it understands that the column for the relationship is in the destination table only?
Right after I asked this question, I found my own answer: using hasOne as explained in http://grails.org/doc/latest/ref/Domain%20Classes/hasOne.html
There is the possibility to disable the #OneToMany relationship join table with the #JoinColumn annotation. The default is a join table.
What are the advantages and disadvantages for a production system for example?
When should I use a join table and when not?
Thank you.
By default #OneToMany will create a join table only if you'll use unidirectional relationship.
In other words, if you have Employee and Project entities and the Employee entity is defined as follows (assume there is no orm.xml entries for these entities):
#Entity
public class Employee {
// ...
#OneToMany
Set<Project> projects;
}
#Entity
public class Project {
// ...
}
the JPA provider will create a join table (notice there is no mappedBy attribute in #OneToMany annotation as there is no reference to Employee entity from the Project).
On the other hand, if you'll use bidirectional relationship:
#Entity
public class Employee {
// ...
#OneToMany(mappedBy="employee")
Set<Project> projects;
}
#Entity
public class Project {
// ...
#ManyToOne
Employee employee;
}
The join table will not be used, as there "many" side will be used to store the foreign key for this relationship.
However, you can force to use join table even in cases when you have bidirectional #OneToMany relationship with defined mappedBy attribute. You can achieve it using #JoinTable annotation on the owning side of the relationship.
There is also a possibility, as you've mentioned, to use #JoinColumn in case where join table would be used by default (unidirectional #OneToMany relationship).
It's best to test the FK and join table performance difference for yourself. I can just guess that less joins (in this case: FK) seems to have better performance.
Moreover, sometimes the DBA defines the database schema and you just need to fit your mappings to the existing schema. Then you have no choice over FK or join table - that's why you have a choice.
Join tables are needed for polymorphisms. E.g., if Employee and Manager links the same project and they are mapped with one-table-per-class strategy, at the relational DB level, the only way to know that project( id = 1, emp_id = 10 ) refers to a manager is to put emp_id in the manager_2_employee table. If one is not in such a situation, then emp_id can go directly into project.
As mentioned in comments above, by default hibernate goes for join table.
This results in better db normalization.
If having a choice, JoinColumn gives better performance over the join table as need for the joining of an extra table in the SQL Query is removed.
I'd like to improve my understanding of cardinality constraints in ER diagrams.
I have two entities:
User
Location
But, I want the relationship between these two entities to be many-to-many (a user can be in many locations and a location can have many users).
To do this I need to introduce an association class UserLocation.
Is it correct to say I now have 3 entities?
If I were to draw an ER diagam of the above, would I draw in the UserLocation entity, and would the cardinality look like this?
User 1 ------ * User Location * ------ 1 Location
You do not need a third entity.
In the Entity world, this is modeled like this:
The entity User has a list of Locations.
The entity Location has a list of Users.
In the Relational world, this is modeled like this:
A table USER, with primary key USER_ID
A table LOCATION, with primary key LOCATION_ID
A table USER_LOCATION, with two foreign keys, one to each of the above tables.
I believe that in the Relational diagram the "intermediary" is not visible. So, I think you would need something like this:
User * ------- * Location
It all depends on the type and level of entitiy mapping you are doing.
You can express the relationship as it is
Entity 1 <> Entity 2
Such as using the 'Crows Feet' to represent the many relationship.
When normalising the map you would break up the many to many relationships with an intermediate table, this would normally contain the primary keys of both of the many tables
Entity 1 > Entity 3 < Entity 2
Where Entity 3 (your intermedite table) would hold PK's for both tables, and ocassionally any other data, such as a unique ID etc.