Doctrine ORM: How to define a 1-n realtionship with a n-n connecting table - doctrine

So, this is a bit complicated: I have two tables, say cats and dogs.
They are in a many-to-many relationship (could be called friendships or whatever), so that Doctrine automatically creates a table cats_dogs for me with the appropriate fields. (that is rowid, cat_id, dog_id per default.)
Now, imagine I have a third table, award, where I want to award one of these friendships. Here I therefore need a field that references one row in cats_dogs. However, since this table does not really exist between my models, (Doctrine handles it for me) what would be the most elegant solution for this?
In the end, I want in my award model two fields, a cat and a dog, who need to be in a friendship.
I am using the annotation driver.

What stops you from manually creating the m:n table instead of having doctrine do it for you?

The Doctrine aims is to map objects from an E/R schema and to make easier the access to object connections. Therefore I believe that the table cats_dogs automatically provided by Doctrine is necessary as it is. It is concise and hits its purposes, i.e. it provides a list of all dogs of a cat or, vice versa, all the cats of a dog.
Thus, I can conclude that it is preferable to create a third entity (besides Cat and Dog) named Award which provides a one-to-one relationship with Cat and another one-to-one relationship with Dog. Making it consistent with the cats_dogs table is only up to you, and is not a Doctrine task by default. E.g., you can use some cascade persist option.
I believe that this is the most effective solution with Doctrine.
As a final remark, consider that each table should map a specific relationship between one or more entities, and in fact the table cats_dogs represents the friendship relationships, while the table Award will represent the awarded relationship relationship between two friends.

Related

Should I create three models or a polymorphic type

I have a Laravel 8 application and am wondering how to solve the problem of how to solve a typical polymorphic issue. I have an Employee model. That Employee can be an ExecutiveEmployee or EntryLevelEmployee. There will be methods an ExecutiveEmployee has that an EntryLevelEmployee doesn't have and the inverse is also true.
Using Laravel 8, is it right to create a base Employee model (without a corresponding table?) and then create two models named ExecutiveEmployee and EntryLevelEmployee that inherit from Employee? This would also imply that both employee types will have two different database tables, even though there will be a lot of overlapping data.
Does it make sense to just have one Employee model and create a migration that has the employee type listed in the model? I am assuming that it's ok if an EntryLevelEmployee has some database attributes which are relevant to it that may or may not be relevant to an ExecutiveEmployee type here, or is that an incorrect assumption?
What's the correct way to model this in Laravel 8? I prefer to keep everything in one table because of how similar the models are. I do have to keep in mind that there will be data that one has that the other doesn't. There will be different accessor methods as well.
Is it possible to have everything in one employees table while utilizing multiple models? Meaning, if I create two models named ExecutiveEmployee and EntryLevelEmployee they would both query the underlying table employees?
UPDATE 1
The more I research, the more I think polymorphism is the incorrect approach here and what I might need is Single-Table Inheritance. This package seems to bring the capability to Eloquent. Would there be a good reason to not use this?
I would use polymorphic relationships in this case, because you are more flexible and have less coupling.
Using the Single Table Inheritance (STI), you can add type specific columns in the employees table and make them nullable. But think about adding/removing types in the future.
executive_employees
id - integer
executive_specific - string
entry_level_employees
id - integer
entry_level_specific - string
employees
id - integer
name - string
email - string
employable_id - integer
employable_type - string
As for the STI the same would be
employees
id - integer
name - string
email - string
type - string
executive_specific - nullable string
entry_level_specific - nullable string
So STI would be suitable when you don't have type specific columns. But you want to add specific behavior in your code. For example a User type (Admin, Author).
Even so, it's a matter of preferences.
It really depends on the state and behavior of your employee object.
Below are few points I will consider to make a decision
If your objects' states/properties are different then definitely you will create different models as your data will be stored in different tables.
If most states/properties are same and some are different, you can
consider storing all in one table/model and for the difference in
behavior create separate table like Ron Van Der Heijden has
suggested and you can consider query scope with that to make
transaction with database.
And another view will be
How many JOINs you will create if you will create different tables,
will that impact the performance and other stuffs, will it make your
code complex?
Can you make simpler relations and handle stuffs independently?
When you are making an API, will your
code make the api overworking? or you need to create too many request
for any operation?
These stuffs will decide how you will make a decision.
Update 1:
Another point I would like to add about the package you are thinking to use, consider using a parent key in table and you can define relationships in a single model.I do not think you need to use a package, you can define it yourself, I guess.
I don't understand why you don't create a simple one-to-many relation. Based on the information you provided, the polymorphic relation looks unnecessary. I think the right way is to create employee_roles table and relations. Then you can give different permissions to different employee types. There are several ways to do that. You can create a middleware to create route restrictions. You can check the role before executing a function in the controller, and run only if the employee has permission. You can use if-else in blade not to render the parts that can't be used by auth user etc.
If you have different “types” of employees, and each employee type should have different logic then yeah, that sounds like a polymorphic relationship.

When polymorphic relation shouldn't be used?

Is it okay to use a polymorphic relation when there are lets say 6 common columns and 2 columns with different names?
I need to track car maintenance and refueling.
maintenances - table
-date
-km_driven
-info (refers to maintenance info )
refuelings - table
-date
-km_driven
-amount (refers to amount in liters)
So, should i use polymorphic relationship or not? Is it ok if there are more different columns per model?
IMHO for your case I will go for single table inheritance (STI), but you need a library like this tightenco/parental or this one Nanigans/single-table-inheritance.
Laravel codebase has no support for STI without an external library. You can try to use polymorphic relation to solve your case but you will end up with 3 different tables. I think you want to use a single table with two or even three models so my advice is to try one of the STI library above.
STI is appropriate when your models have shared data/state. Shared behavior is optional because can be defined per Model. An example could be different type of vehicle Models: Car, Truck, Bike etc..
With Polymorphic Relations instead, a model can belong_to several models with a single association. This is useful when several models do not have a relationship or share data with each other, but have a relationship with the polymorphic class. An example could be the Comment Model that can belongs to other Models: User, Post, Image etc..

Dynamically set the table name in a "has many" relation model

In my database schema, I have multiple tables that hold generic data for objects, for instance I have a user table and a user_data, post table and post_data, and so. these *_data tables all hold a foreign key to the object and a pair of key-value. now in my laravel models I would like to have a single data models for these tables (rather than a model for every single one) and represent the has_many relation in a dynamic way where somehow I can define the table name according to the parent model. I think the parent model would have something like:
return $this->hasMany('data');
but I don't know how to express the inverse relation nor how to tell laravel which *_data table to use. so my question is, is it possible? and if so, how?
You have two options.
Either create a model for each data_* table and use the relation as stated with $this->hasMany('data'); and $this->belongsTo('User'); in the data table and the user table.
Or you can use Polymorphic relations, I personally prefer the polymorphic relations solution, more neat.

How to Program a Spring with Hibernate web app?

I am Working on web application where i have 90 fields for a Person class which are divided in to family details,education details, personal details etc....
I want separate form for each, like for family details has-father name, mother name siblings etc... fields and so on for other
I want separate table for each detail with common reference id for all tables
My question is how many bean classes should i write? Is it with one bean class can i map from multiple forms to multiple tables?
class PersonRegister{
private Long iD;
private String emailID;
private String password;
.
.
}//for register.......
once logged in i need to maintain his/her details
Either
class person{
}
or
class PersonFamilyDetails{}
class PersonEducationDetails{}
etc
which way software developing standards specify to create?
Don't go overboard, I believe in your case single but very wide (i.e. with a lot of columns) table would be most efficient and simplest from maintenance perspective. Only thing to keep in mind is too query only for a necessary subset of columns/fields when loading lots of rows. Otherwise you'll be fetching kilobytes of unnecessary data, not needed for particular use case.
Unfortunately Hibernate doesn't have direct support for that, when designing a mapping for Person, you'll end up with huge class and even worse - Hibernate will always fetch all simple columns (and many-to-one relationships). You can however overcome this problem either by creating several views in the database containing only subset of columns or by having several Java classes mapping to the same table but only to subset of columns.
Splitting your database model into several tables is beneficial only if your schema is not normalized. E.g. when storing siblings first name and last name you may wish to have a separate Sibling table and next time some other family member is entered, you can reuse the same row. This makes database smaller and might be faster when searching by sibling.
Your question comes down to database normalization, as described in-depth by Boyce and Codd, see
http://en.wikipedia.org/wiki/Database_normalization.
The main advantage of database normalization is avoiding modification anomalies. In your case, if you got one table with for each person e.g. father-firstname and father-lastname, and you have multiple people with the same father, this data will be duplicated, and when you discover a typo in the father-lastname, you could modify it for one sibling, and not for the next.
In this simplified case, database design best practices would call for a first normalization into a separate table with father-id, father-firstname and father-lastname, and your person table having a one-to-many relation to it.
For one-to-one relations, e.g. person->personeducationdetails, there's some debate. In the original definition of 1st Normal Form, every optional field would be normalized by putting it's own table. This was later weakened by introducing 'null' in relational databases, see http://en.wikipedia.org/wiki/First_normal_form#cite_note-CoddRule-12. But still, if a whole set of columns could be null at the same time, you put them in a separate table with a one-to-one relation.
E.g. if you don't know a person's educationdetails, all of its related fields are null, so you better split them off in a separate table, and simply not have a personeducationdetails record for that person.

use sequence object for multiple tables to ensure querability on join

I am using Oracle. I have two tables:
Cat (cat_ID, cat_name, cat_age, cat_strength)
Dog (dog_ID, dog_name, dog_age)
Sometimes I need to get all pets into one query result. I was thinking of creating an animal_seq sequence that can be used by both Cat and Dog tables so that they never have duplicate IDs across tables and then when joined can be easily searched/queried whatever.
Is this bad practice? If so, why? Are there better ways to design the tables (eg just one Animal table, or multiple inheritence). Personally, I try to avoid inheritence due to the performance issues of joins.
Having a single sequence is totally acceptable and safe. Oracle ensures multiple reads to a sequence always returns a unique value so you shouldn't have any problems with duplicate keys.
If the the schema between CAT and DOG is truly unique and an additional animal entity will also be unique, I would keep separate tables. If you are going to maintain the same information about cats, dogs, monkeys, etc., I would recommend putting them into a single ANIMAL table. You'll have to give more information about the application/database for us to know what to recommend.
With your current design what if you wanted to record birds or rabits or any other animal ?You would have to create tables for each type.
I would say use KISS(Keep it simply stupid) principle and have one table and join to another table called ANIMAL_TYPE( animal_type_id,Animal_type_name) that way you can make the sure ids are not duplicate and you can tend should you want to record other animal types.
I think you are looking for a base table, animal. Then you have two sub classes cat and dog. Such a design will help you when you add information such as "owner" of that animal, or "animal observation" or whatever the purpose of your application is.
table animal(
animal_id
,animal_type <-- Discriminator column with for example C for cat, D for dog
,name
,age
,primary key(animal_id)
)
table cat(
animal_id
,cat_strength
,primary key(animal_id)
,foreign key(animal_id) references animal(animal_id)
)
table dog(
animal_id
,dog specific attributes here
,primary key(animal_id)
,foreign key(animal_id) references animal(animal_id)
)
As you can see, I've moved up common attributes to the base table animal, while keeping the specific attributes for the subclasses in the sub class tables.

Resources