polymorphic association alternative - mysql

I'm trying to design a part of my database which should cover users login. My users can login with "local", "facebook" or "google" account.
What I have is a table users that contains two columns, login_type login_id.
The values of login_type can be "local", "facebook" or "google" which refers to three tables: local, facebook and google.
login_id is the id of the login_type referenced table.
I don't like this polymorphic association and would redesign this part to keep the database simple and coherent by creating tables that references as usual with foreign key.
Appreciate any suggestion
Regards

What you are doing is a trick known in Object Relational Mapping (ORM) systems as a discriminator column. The problem with it, as you already understand, is that referential integrity goes out the window, because you cannot declare your login_id as being a foreign key that maps to another table, because it may map to one of three possible tables, and the table that it maps to is chosen by the value of the login_type column.
The way to do this correctly might seem a bit strange, but it does guarantee referential integrity.
Table users columns:
id primary key
local_users_id foreign key, references local_users(id)
facebook_users_id foreign key, references facebook_users(id)
google_users_id foreign key, references google_users(id)
So, the login_type column is abandoned, and instead you introduce three nullable foreign keys: local_users_id, facebook_users_id, and google_users_id. Only one of them may be non-null.
You can make sure that only one of them is non-null in code, or even in the database, with a trigger or perhaps even with a constraint.

Related

Should I use foreign keys in this example?

I have an (example) database consisting of three tables: user, car, key. The user can have multiple cars, and each car can have multiple keys. As of now, the car and key tables have a foreign key associating themselves with the user and car (below) - and this works fine.
My issue is, if a car were to no longer exist and be deleted, this wouldn't necessarily mean that the key no longer exists. However once the car has been deleted, there is no way to associate the key to the user - as the car being referenced by the key's foreign key is now gone.
I realise I could store the user ID alongside each key, but I assumed this beat the point of having foreign keys and wasn't the best way of doing it.
So, what's the most acceptable way around this issue?
Thanks!
As the key is still there and has some meaning (as you don't want to delete the key),
I would "soft delete" the car, eg. add a bit column "deleted" to the table car.

A many-to-many primary key for "appointments"

I know this question has been asked a lot but my example seems different.
I have two entities: Doctor and Client, and a many-to-many relationship between them to create the entity Appointment, which has, say "appointment_date_time" for an attribute.
I'm using the foreign keys from Doctor and Client to create a composite primary key in Appointment, but since there can be many appointments between the same doctor and person, should the "date_time" also be included as part of the primary key so there's no duplicates? Or would the two foreign keys be enough to query off of?
Thanks!
Your PRIMARY KEY needs to always be unique, so including the datetime would make an usable composite PRIMARY KEY that would (probably, unless you could have multiple appointments at the same time for 2 different purposes, which might happen) be unique.
However this is unlikely the best approach practically speaking, as if they move the appointment then this time will change (or maybe changed the doctor). Then you have no way to reference the appointment statically, say for example if you associated some extra data to it during creation or had to reference it as an audit entry. It also means any references to it that you do create would need to store all 3 columns.
As such I would simply look to create an auto incrementing primary key in this case, and simply index on both doctor and client for fast searches.

Renaming foreign keys to fit the context of a table

When using a foreign key in a table, is it good form to change the name of the key for that table to make it clear what function the key performs in the table, or is it good form to retain the original name, to make it clear that it is a foreign key?
Example:
a table keeps track of users, the primary key is user_id
a second table stores articles on the website and keeps track of the author with the foreign key user_id.
In the context of the second table it would make more sense to call the foreign key author. In the context of the whole database it would make more sense to call the foreign key user_id
Is there a general convention that deals with this situation, or is that what comments are for?
Well, if you have a movie table you wouldn't want columns called person_id and person_id, but rather producer and director, or perhaps producer_id and director_id, or maybe producer_person_id and director_person_id.
I know movies can have multiple directors and multiple producers; this was just an example. Any case in which a table has two foreign keys to the same table will show you that you cannot in principle stick completely to a convention of using only the table name in the column name. You can use both (as in the producer_person_id example) but that leads to long column names.
Don't use comments. No one reads them. Okay that was just snark, perhaps, but in general favor descriptive names to comments!
Aside from the two-foreign-key issue, I'm not really aware of any univerally accepted convention.
It is conventional to know the database schema's modelling and designing. Whatever makes sense to the database administrator. Business logic is not concerned with how the database is named, only the results. For the database administrator if it make more sense to rename the foreign key author_id to refer to user_id of another table then do so and notate it in some documents that T2.author_id must exist in T1.user_id. When transitioning from modelling to designing the database (which is where you are now) it would make sense to just keep it simple, but you can change the foreign key names so long as you can remember them (and document them as well).

Making sure a table entry is unique

I have mysql database table for addresses, it contains separate columns for post code / street /town.
How can I make sure a full table entry is unique rather than just one of the columns alone?
Make a composite key on {post code, street, town}.
A key can be primary (PRIMARY KEY) or alternate (UNIQUE constraint).
BTW, can two different towns have the same post code? If not, you don't need the town in the key. In fact, consider normalizing your model by "extracting" the town to a separate table.
mysql allows you to have a unique key for n number of fields or columns. When you declare this column as unique , mysql checks for the constraint for duplication.
For more info read this mysql unique key
"The UNIQUE and PRIMARY KEY constraints both provide a guarantee for uniqueness for a column or set of columns."
But, i suggest the front end validation for making the user comfortable (just incase u had not thought of it ;) )
A database table may have multiple unique keys, so it will reject any INSERT queries that violate the constraints you set in the table.
Simply set the other columns to be unique and you should find that your problem is solved.

Hibernate, how to model this relationship

I have the below tables.
create table logical_id_seq (
logical_id int auto_increment,
primary key(logical_id)
);
create table mytable (
physical_id int auto_increment,
logical_id int not null references parent(logical_id),
data varchar(20),
primary key(physical_id)
);
The second table uses first table auto-generated value as its value. I am not sure how to model this in hibernate.
I read http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-onetoone, but I doesn't seem to understand.
It's actually hard to say, I don't know what you want to represent at the object level: is it a one-to-one foreign key association? a many-to-one association? is the association bi-directional? Using an ORM means thinking objects more than tables and it usually help to provide the object model.
I'll assume this is a one-to-one foreign key association. Here is what Java Persistence with Hibernate recommends:
7.1.2 One-to-one foreign key associations
Instead of sharing a primary key, two
rows can have a foreign key
relationship. One table has a foreign
key column that references the primary
key of the associated table. (The
source and target of this foreign key
constraint can even be the same table:
This is called a self-referencing
relationship.)
Let’s change the mapping from a User
to an Address. Instead of the shared
primary key, you now add a
SHIPPING_ADDRESS_ID column in the
USERS table:
<class name="User" table="USERS">
<many-to-one name="shippingAddress"
class="Address"
column="SHIPPING_ADDRESS_ID"
cascade="save-update"
unique="true"/>
</class>
The mapping element in XML for this
association is <many-to-one> — not
<one-to-one>, as you might have
expected. The reason is simple: You
don’t care what’s on the target side
of the association, so you can treat
it like a to-one association without
the many part. All you want is to
express “This entity has a property
that is a reference to an instance of
another entity” and use a foreign key
field to represent that relationship.
The database schema for this mapping
is shown in figure 7.3.
Figure 7.3 A one-to-one foreign
key association between USERS and
ADDRESS
An additional constraint enforces this
relationship as a real one to one. By
making the SHIPPING_ADDRESS_ID
column unique, you declare that a
particular address can be referenced
by at most one user, as a shipping
address. This isn’t as strong as the
guarantee from a shared primary key
association, which allows a particular
address to be referenced by at most
one user, period. With several foreign
key columns (let’s say you also have
unique HOME_ADDRESS_ID and
BILLING_ADDRESS_ID), you can
reference the same address target row
several times. But in any case, two
users can’t share the same address for
the same purpose.
Let’s make the association from User
to Address bidirectional.
Inverse property reference
The last foreign key association was
mapped from User to Address with
<many-to-one> and a unique
constraint to guarantee the desired
multiplicity. What mapping element can
you add on the Address side to make
this association bidirectional, so
that access from Address to User is
possible in the Java domain model?
In XML, you create a <one-to-one>
mapping with a property reference
attribute:
<one-to-one name="user"
class="User"
property-ref="shippingAddress"/>
You tell Hibernate that the user
property of the Address class is the
inverse of a property on the other
side of the association. You can now
call anAddress.getUser() to access
the user who’s shipping address you’ve
given. There is no additional column
or foreign key constraint; Hibernate
manages this pointer for you.
If what you have is actually a real many-to-one association, it should be pretty easy to adapt the above solution.