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

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.

Related

How to do Hibernate ORM mapping for a 2D Array

I am new to ORM and got stuck on the following issue (simplified for the discussion here):
I am modelling a tournament, with competitors and disciplines. Both have their own entity class. Competitors compete in each discipline exactly once, and receive a score. As long as a competitor has not yet competed in a given discipline, there is no score.
Data Model:
A straightforward DB design would be a scores table with foreign keys to both the competitors table and the disciplines table. That is, I would set up two one-to-many relationships, plus integrity constraints on the foreign keys - I cannot delete a competitor or a discipline as long as there are scores that reference either one.
But how do I map this 2D Array (competitors/disciplines) onto my classes? I am using Java and Hibernate.
My current solution is to put a collection of scores into the Competitor entity class, and similarly for the Disciplines class. This creates a bidirectional relationship with a join table for each of the two entity classes. Is this the recommended way to do the mapping?
It does map the relationship form the perspective of each domain class, but it misses out on the 2D array structure. I want to output the entire array - on a UI, for example - with rows for competitors, columns for disciplines, and the scores in the corresponding table cell. Building such an output from the entity classes as just described is tedious and requires (a) to iterate through the competitor collection and then (b) look up the corresponding discipline - or the other way around.
Ideally, I would like to have a hash map with two keys, like the Guava Table, or a nested hash map. I suppose that there is no native Hibernate mapping for this kind of advanced collection. But maybe there is a best practice how to implement it using custom queries?
But how do I map this 2D Array (competitors/disciplines) onto my classes? I am using Java and Hibernate. My current solution is to put a collection of scores into the Competitor entity class, and similarly for the Disciplines class. This creates a bidirectional relationship with a join table for each of the two entity classes. Is this the recommended way to do the mapping?
IIRC, an implicit join table doesn't allow to add the score. Even if it did, I would't like it as the scores are actually the main information. So I'd go for an explicit table.
class Score {
#ManyToOne(optional=false)
Competitor competitor;
#ManyToOne(optional=false)
Discipline discipline;
}
This should provide everything you need. You may also want a Set<Score> or even Map<Discipline, Score> in the class Competitor (and vice versa in the other class), but you may not need it. The mapping would probably use #ManyToMany(mappedBy="competitor") and #MapKey... I haven't used it for long as I found out I don't really need it.
Ideally, I would like to have a hash map with two keys, like the Guava Table, or a nested hash map.
Using the default #ManyToOne(fetch=EAGER), the needed competitors and disciplines get fetched automatically using a JOIN. I'm afraid, a List is all you can get, but iterating it once and filling a Guava Table is trivial:
list.stream()
.forEach(score -> table.put(score.competitor, score.discipline, score));
Just don't forget that the entities are mutable but mustn't be mutated when used as keys. Obviously, you should only fetch the entities you need rather than filtering the Table. However, once you have the Table, you can use all its operations at will; Hibernate won't help you here anymore, but you don't need it (and you don't want to hit the DB again).

Sql to object, many to many with field

I am working on a little website. The database was created and we need to create objects from sql now.
Usually, in "Many to many" relation, I use a list to represent this relation. (List of ingredient in recipe, and if I need, a list of recipe in ingredient).
But I don't know what is the best way when the junction table contain field.
For example with theses tables:
###### #################### ##########
RECIPE INGREDIENT_IN_RECIPE INGREDIENT
id id_ingredient id
name id_recipe name
quantity
other
Is there a best way to create object from this sql?
I don't know if:
I need to create an third object "IngredientInRecipe". And list it on recipe/ingredient?
Maybe create fields quantity/other in ingredient and use it only when I want to handle ingredient as "ingredientinrecipe"?
Or create a Subclass of Ingredient with quantity/other?
Maybe I'm totally wrong and I just have to create list in recipe and use sql query or array for other things but I'm little bit lost.
This is a simple association class and you would model it like this:
You concrete object model with single tables it pretty fine.
The answer here is based on the question is the INGREDIENT_IN_RECIPE an entity by itself, or is it just a relational table to create the many to many in the db.
Currently, INGREDIENT_IN_RECIPE contains additional information, that is really important and further specifies the relation between RECIPE and INGREDIENT, so this qualifies it is a proper entity.
IMHO, the best way here is to create a entity class for the INGREDIENT_IN_RECIPE table and list it on the RECIPE entity class at least. You need to check if the relation from the INGREDIENT entity is really needed and useful.

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.

Best practice for database dictionary in 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.

Hibernate Master-SubDetails Mapping

I'd like to explore Hibernate and used it in my project instead of JDBC.
My table design is highly normalized.
Suppose, I have this use case: Each insurance applied by a customer has one associated rateplan. Usually, in RDBMS this is implemented using two tables like below.
Table Insurance:
id long;
accountHolder varchar;
ratePlanId int; -->Rate Plan Id is Foreign Key to the RatePlanTable
Table RatePlan:
ratePlanId int;
ratePlanDesc varchar;
discountRate double;
Now, my question is..does this qualify as a onetomany relationship?
Most of the examples that I am seeing on the net regarding onetomany, involves some sort of collections (e.g An Order has a list of products). And when represented in class is translated below, which I think is really a one to many case?
public class Order{
private List products;
}
But how about my case? I don't think that it is a onetomany or I am just mislead by the examples?
How can I do a hbm mapping for my two classes? In my case, I would create two class to represent the two tables, but I am not sure how the hbm.xml would look like for the two class.
Yes, it is a one to many relationship, in that one rate plan is associated with many insurance policies. In entity traversal, when you would go from the Policy, you would get one Plan object, and conversely, from a Plan object, you would get a list of Policy objects.

Categories