In a table per concrete subclass setup, is it possible to switch a row/object from one table to another? How would that work?
For example we have a base class Person.java with pk person_id.
Then we have 2 subclasses Police.java and Firefighter.java both of these are mapped by corresponding tables PERSON and FIREFIGHTER again with primary key person_id.
Now suppose a Police officer becomes a firefighter or vice-verca, how will this work? Can this work in hibernate? Any examples?
All common rows have to be identical in the different tables. In that strategy you have to duplicate rows. The only interesting illustration I found is in The Java Geek.
According to the Java EE 6 tutorial, the support of this strategy is optional (not available in Glassfish they say).
Polymorphism is poorly supported, so your use case wouldn't be satisfied properly: you would have to remove your policeman from the police before creating a brand new firefighter.
I guess you won't find what what you are looking for with another strategy if you want to switch between different rows among the different entities:
In the Joined Subclass Strategy all common fields have to be mapped in the base table
In the Single Table per Class Hierarchy Strategy (poor designation) you have all data in a single table with a discriminator column
Related
According to the Hibernate docs, MappedSuperclass allows mapping inheritance, where the super class is not treated as an entity, and where polymorphic queries that fetch objects by the base class are not supported.
On the other hand, the table per class strategy is similar in terms of the generated schema in the DB, except that it maps the super class to a table if it is not an abstract. However it supports polymorphic queries.
My question is: why would anyone use the #MappedSuperclass strategy? Is there a performance issue implied if the parent class is treated as an entity? Any ideas around this is appreciated.
#MappedSuperclass
By default, properties of the superclass are ignored and not persistent!
You have to annotate the superclass with #MappedSuperclass to enable embedding of its properties in the concrete subclass tables.
You can override column mappings from the superclass in a subclass with the #AttributeOverride annotation or several with #AttributeOverrides.
You could declare the identifier property in the superclass, with a shared column name and generator strategy for all subclasses, so you wouldn’t have to repeat it. But it’s optional!
The main problem with implicit inheritance mapping is that it doesn’t support polymorphic associations very well. In the database, you usually represent associations as foreign key relationships. If the subclasses are all mapped to different tables, a polymorphic association to their superclass can’t be represented as a simple foreign key relationship.
Polymorphic queries that return instances of all classes that match the interface of the queried class are also problematic. Hibernate must execute a query against the superclass as several SQL SELECTs, one for each concrete subclass.
A further conceptual problem with this mapping strategy is that several different columns, of different tables, share exactly the same semantics. This makes schema evolution more complex. For example, renaming or changing the type of a superclass property results in changes to multiple columns in multiple tables. Many of the standard refactoring operations offered by your IDE would require manual adjustments, because the automatic procedures usually don’t account for things like #AttributeOverrides. It also makes it much more difficult to implement database integrity constraints that apply to all subclasses.
So, this approach is a good chose for the top level of your class hierarchy,
where polymorphism isn’t usually required, and when modification of the superclass
in the future is unlikely.
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
The database identifier and its mapping have to be present in the superclass, to share it in all subclasses and their tables. This is no longer optional, as it was for the #MappedSuperclass mapping strategy.
Note that the JPA standard specifies that TABLE_PER_CLASS is optional, so not all JPA implementations may support it. The implementation is also vendor dependent — in Hibernate, it’s equivalent to a <union-subclass> mapping in the old native Hibernate XML metadata.
The advantages of this mapping strategy are clearer if we examine polymorphic queries. The tables are combined with a UNION operator, and a literal is inserted into the intermediate result; Hibernate reads this to instantiate the correct class given the data from a particular row. A union requires that the queries that are combined project over the same columns; hence, you have to pad and fill nonexistent columns with NULL. You may ask whether this query will really perform better than two separate statements. Here you can let the database optimizer find the best execution plan to combine rows from several tables, instead of merging two result sets in memory as Hibernate’s polymorphic loader engine would do.
Another much more important advantage is the ability to handle polymorphic associations. Hibernate can use a UNION query to simulate a single table as the target of the association mapping.
So, this approach is a good chose when you need to use polymorphic queries and associations.
P.S. This is almost verbatim quotation from the excellent book: Java Persistence with Hibernate (Bauer, King, Gregory)
meaning a class whose mapping information is applied to the entities that inherit it.
Short version for the hasty:
There's various tables/entities in my domain model which have the same field (a UUID). There is a table where I need to link rows/instances of such entities to other JPA-managed entities. In other words, the instance of the field in that link table won't be known up-front. The two approaches I can think of are:
Use an abstract entity and a TABLE_PER_CLASS strategy, or
use an #MappedSuperClass store the class name of the instance in the link table as well, or something similar that lets me define logic for getting the actual instance from the right table.
Both have advantages and disadvantages in terms of complexity and performance. Which do you believe to be best, is there maybe a third option, or have you tried something like this in the past and would advice/strongly warn against?
Long version in case you want more background:
I have a database/object model wherein many types have a common field: a universally unique identifier (UUID). The reason for this is that instances of these types can be subject to changes. The changes follow the command model and their data can be encapsulated and itself persisted. Let's call such a change a "mutation". It must be possible to find out which mutations exist in the database for any given entity, and vice-versa, on which entity a stored mutation operates.
Take the following entities with UUIDs as an (extremely simplified) example:
To store the "mutations", we use a table/entity called MutationHolder. To link a mutation to its target entity, there's a MutationEntityLink. The only reason this data isn't directly on the MutationHolder is because there can be direct or indirect links, but that's of little importance here so I left it out:
The question comes down to how I can model the entity field in MutationEntityLink. There are two approaches I can think of.
The first is to make an abstract #Entity annotated class with the UUID field. Customer, Contract and Address would extend it. So it is a TABLE_PER_CLASS strategy. I assume that I could use this as a type for the entity field, although I'm not certain. However, I fear this might have a serious performance penalty since JPA would need to query many tables to find the actual instance.
The second is to simply use #MappedSuperClass and just store the UUID for an entity in the entity field of MutationEntityLink. In order to get the actual entity with that UUID, I'd have to solve it programmatically. Adding an additional column with the class name of the entity, or something else that allows me to identify it or paste it in a JPQL query would do. This requires more work but seems more efficient. I'm not averse to coding some utility classes or doing some reflection/custom annotation work if needed.
My question is which of these approaches seems best? Alternatively, you might have a better suggestion, or notice I'm missing something; for example, maybe there's a way to add a type column even with TABLE_PER_CLASS inheritance to point JPA to the right table? Perhaps you've tried something like this and want to warn me about numerous issues that would arise.
Some additional info:
We create the database schema, so we can add whatever we want.
A single table inheritance strategy isn't an option. The tables must remain distinct. For the same reason, joined inheritance doesn't seem a good fit either.
The JPA provider is Hibernate and using things that are not part of the JPA standard isn't an issue.
If the entities don't have anything in common besides having a uuid I'd use the second approach you describe: use MappedSuperclass. Making the common superclass an entity would prevent you to use a different inheritance strategy if needed, would require a table for that super entity even if no instances exist and from a business point of view it's just wrong.
The link itself could be implemented in multiple ways, e.g. you could subclass MutationEntityLink for each entity to map (e.g. CustomerMutationEntityLink etc.) or do as you described it, i.e. only store the uuid as well as some discriminator/type information and resolve programatically (we're using that approach for something similar btw.).
You need to use #MappedSuperclass while inheriting associations/methods/properties whereas TABLE_PER_CLASS is generally used when you have entity and sub-entities. If there are entities having an association with the base class in the model, then use TABLE_PER_CLASS since the base class behaves like an entity. Otherwise, since the base class would include properties/attributes and methods which are general to such entities not related to each other, using #MappedSuperclass would be a better idea
Example1: You need to set alarms for some different activities like "take medicine", "call mom", "go to doctor" etc. The content of the alarm message does not matter, you will need a reminder. So use TABLE_PER_CLASS since alarm message, which is your base class is like an entity here.
Example2: Assume the base class AbstractDomainObject enables you to create login ID, loginName, creation/modification date for each object where no entity has an association with the base class, you will need to specify the association for the sake of clearing later, like "Company","University" etc. In this situation, using #MappedSuperclass would be better.
I am taking a table per subclass approach to map some data using hibernate. Typically at the database layer I would introduce a type column in the abstract table and it's subtables, which would enforce that an abstract record can only relate to a subrecord of a matching type. However from looking at various resources it seems to state that the hibernate discriminator is used for legacy databases. Does this mean I am taking the wrong approach?
Table Per (Sub)Class means you have one table per class and no abstract table. Thus a discriminator is not needed. If you have Single Table or Joined inheritance, then you'd need a discriminator.
Edit: actually, Hibernate's Table Per Subclass seems to be the Joined inheritance strategy. However, this is stated by the documentation:
Hibernate's implementation of table per subclass does not require a discriminator column.
As stated above, Hibernate table per subclass does not require a discriminator.
According to the same source:
"... If you want to use a discriminator column with the table per subclass strategy, you can combine the use of subclass and join ..."
See section 9.1.3 in http://docs.jboss.org/hibernate/core/3.3/reference/en/html/inheritance.html#inheritance-tablepersubclass
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.
I have two classes Parent and Child.
class Child extends Parent {
private String extraField1;
private String extraField2;
...
}
Child class has 2 extra fields extraField1 and extraField2.
Q1. Should I make two diff. tables in the databse: one for Child and other for Parent?
or
Q1. Should I add two columns in the Parent table (each column for one extra field) and store the Child in the Parent table.
=============================== EDITED =======================================
Yes, Child and Parent are classes in the same hierarchy.
Should there be 2 datatables for a Parent and Child class in Java?
There is no universal answer to this question. There are actually several techniques to map an inheritance hierarchy into a relational database and they all have advantages and disadvantages. Choosing one or the other depends on your context.
Scott Ambler details the various approaches in the section 2. Mapping Inheritance Structures of his famous paper Mapping Objects to Relational Databases: O/R Mapping In Detail that I'm quoting below:
(...) In this
section you’ll see that there are
three primary solutions for mapping
inheritance into a relational
database, and a fourth supplementary
technique that goes beyond inheritance
mapping. These techniques are:
Map the entire class hierarchy to a single table
Map each concrete class to its own table
Map each class to its own table
Map the classes into a generic table structure
For a full comparison (with advantages, disadvantages and a recommendation on when to use), have a look at the section 2.6 Comparing The Strategies.
I can't do a better job than him so there is no point at paraphrasing him, just refer to the original paper.
Patterns of Enterprice Application Architecture covers this as well in its chapters on Single-table inheritance, Class-table inheritance, and Concrete-table inheritance.
The coverage is similar to what Pascal has said. There's no One True Way, but the book does give you a good breakdown of costs and benefits, e.g.
The strengths of Concrete Table Inheritance are:
Each table is self-contained and has no irrelevant fields. As a result
it makes good sense when used by other
applications that aren't using the
objects.
There are no joins to do when reading the data from the concrete
mappers.
Each table is accessed only when that class is accessed, which can
spread the access load.
The weaknesses of Concrete Table Inheritance are:
Primary keys can be difficult to handle.
You can't enforce database relationships to abstract classes.
If the fields on the domain classes are pushed up or down the hierarchy,
you have to alter the table
definitions. You don't have to do as
much alteration as with Class Table
Inheritance (285), but you can't
ignore this as you can with Single
Table Inheritance (278).
If a superclass field changes, you need to change each table that has
this field because the superclass
fields are duplicated across the
tables.
A find on the superclass forces you to check all the tables, which leads
to multiple database accesses (or a
weird join).