Best practice for database dictionary in java - java

Is there a "canonical" way to represent a dictionary in - maintained through java persistence - database?
Lets say I have a table of people and there is a column "profession".
Set of professions is restricted but can be extended. Some professions have some special meanings for a system, like a military, or a doctor.
I can use enum for professions and store string (name() method) values in database as it shown here. It is simple and readable.
In database I can have a dictionary table 'profession' with professions (id, name_of_profession), and table 'people' which has foreign key (id_profession) from table 'profession'. Than enum will have an Integer id value that is mapped to id column in 'profession' table.
First solution is short and easy. But in that case, database without application has no integrity. Is the second "legacy" way inappropriate?

I think you have identified the pros and cons of the two approaches. It is really up to you to decide which is better ... for your specific application.
Or to put it another way, "best practice" depends on your application's real requirements.

You could use a combination of both schemes:
Have a Professions table with a single primary key, the name of the profession.
Have a People table with a foreign key constraint in the profession column.
Using a string for a primary/foreign key would affect update performance, but it makes each row in People self-contained, which benefits retrieval operations. Therefore, this alternative might be possible, unless a benchmark says otherwise.

Related

Is it possible to set a custom type in jOOQ not only based on the column name or data type, but on the table name?

I have one project with IDs in the database named like FOO_ID (for the table FOO). I find it convenient to define a small class in Java called FooId wrapping the actual value, and map the FOO_ID column's type to FooId in Java. This allows for better type checking, as I can't accidentally write a "foo id" into a "bar id" column without the compiler giving me an error.
On a new project, all the ID columns are simply called ID in every table. I can't change the database schema, that's out of my hands alas. I would love for <forcedType> to be able to match "column named 'ID' in table named 'FOO'" but right now I can't see how to do that, I don't think it's possible.
Is it possible to constrain <forcedType> based on the table name in addition to the column name? If so, what's the syntax?
Thanks in advance!
Existing feature request
This idea has been discussed on the jOOQ mailing list a couple of times and there's also a pending feature request that will add support for a special generated key type: #6124.
In addition to what you suggested, foreign key types should match their referenced primary key types. The challenge with these types is to make it work for all edge cases including:
Composite keys
Unique keys (which can also be referenced by foreign keys in many databases)
Columns participating in several unique keys / foreign keys
While this is certainly an interesting feature, it is not yet available in jOOQ 3.9.
Workaround
You can work around this limitation yourself by:
Extending the JavaGenerator in order to generate your own type per primary key / foreign key
Using <forcedType/> to replace all single-column key types by your own generated types
This is best done by using the programmatic code generation configuration - otherwise you'd be typing quite a bit of XML (of course, you could also use XSLT to generate the config).

Enum with no ordinal key in a many-to-many relationship

Many of the answers to this question advise not to use ordinals, but just to have a single column with the value of the enum when mapping it to a table in DB.
Is this still a safe approach if I'm going to use this enum-mapped table in a many-to-many relationship?
More detailed, I have a table Car and a table Extras, that I'm modelling as an enum. Then I have a table cars_extras, that holds the nxn relationship and has three columns: id, car_id and extra_id, but I'm not sure if this is a good idea.
You are enforcing the enumeration in two places: in your code as an enum and in the database as a foreign key.
This will ensure that if someone modifies the data directly in the database, they will not accidentally misspell an enum value, but also makes it easy for the programmer to see the valid values.
I have seen people use this approach and then also add a validation step on startup that ensures that the enum table in the database has the sames values as the enum class. It halts with an error if they don't match.

Sharing constants between java and database

Assume that you have a STORE table having a varchar column STATUS that accepts values (OPEN,CLOSED)
On java side, and especially in your sqls I find myself writing queries like this
select * from store where status='OPEN'
Now this is not a written contract and is open to lots of bugs.
I want to manage cases where on db side a new status added or an existing one renamed and handle it on java side. For example if on STORE table if all statuses with OPEN are changed to OP, my sql code will fail.
PS:This question is in fact programming language and database server agnostic, but I tag it with java since I deal with it more.
Your need is a bit strange. Usually stuff don't just "happen" in database, and you don't have to cope with it. Rather, you decide to change things in your app(s) and both change your code and migrate your data.
This being said, if you want to ensure your data are consistent with a well-known set of values, you can create library tables. In your case:
create table STORE (status varchar(32)) -- your table
create table LIB_STORE_STATUS (status varchar(32) unique) -- a lib table for statuses
alter table STORE add constraint FK_STORE_STATUS foreign key (status) references LIB_STORE_STATUS(status) -- constraints the values in your STORE table
Then:
insert into STORE values ('A') -- fails
insert into LIB_STORE_STATUS values ('A')
insert into STORE values ('A') -- passes
With this, you just have to ensure your lib table is always in sync with your code (i.e. your enum names when using JPA's #Enumerated(EnumType.STRING) mapping strategy).
Use enums, you can map directrly to the enum instance name (not necessary to convert to the int ordinal)
But in this case I would have a boolean/bit column called open, and its possible values would be true or false.
(boolean is bit 0/1 in most DB's)

Normalize repeating values in Hibernate - Java

I have a String property of an entity, which is often repeated by other entities - which would (in traditional databases) be mapped to its own table.
For example: I could having a clothing entity, with each item of clothing having its own object or row. Each item will have a brand, but this brand (String) could be repeated by many other clothing items. - it should essentially be a manyToOne mapping, though brand is not an entity on its own, its just a String.
How would I do this in hibernate? Or should I rather create an entity for each brand and use ManyToOne?
Any help will be appreciated!
I think that, just in terms of database normalization (most specifically 3NF), if you are expecting a column to have repeated values, you should export those values to their own table and have a foreign key column. That way, if one of those values changed you could change them all at once.
That would allow you to use ManyToOne in Hibernate as well.
However, if that isn't possible, I would recommend using an Enum.

migrating a hibernate class from a sequence based integer primary key to a GUID primary key while retaining the old keys for backward compatibility?

What strategy is good for migrating a hibernate class from a sequence based integer primary key to a GUID primary key while retaining the old keys for backward compatibility?
We have an extensive class hierarchy (using the joined-subclass model) where the base class has a Long primary key generated from a sequence in the DB.
We are working on transitioning to a GUID primary key, but wish to retain the old primary key (both in old and newly created content) for legacy apps. While the implementation seems fairly straightforward (change the primary key to GUID, add an interceptor to populate the content ID on new content), what pitfalls might I want to watch out for?
Are you sure you want to do this?
I understand wanting GUIDs, but do you really want them to be your database PKs. Some informal testing I did showed that there was about a 10-15% hit in using a GUID PK for joins / searches vs an integer PK. I would suggest you try out some tests with GUIDs on your current population and see what the performance hit is. It may be better to just add a uniquely indexed GUID column to your tables and leave the PKs as they are.
I can't think of a pretty solution but,
I would create another field to hold the GUIDs and auto generate IDs for any records that currently exist and go from there. It will smell a bit but it's better than trying to store incompatible types in the same field if you ask me.
Stupid bugs like "we know that PK is GUID so it's length is always that many"...

Categories