On abstract classes in Java and Hibernate annotations - java

I am planing to create an application relying on DB using Hibernate. I will have some similar classes like teacher and student and so on. In DB they will have some fields with similar names. So I wonder If I can create a class Human with annotations for standard fields like Name, SName and so on so to just extend that class in teacher student and so on. Will it work? Does any one use it in such way?

I would suggest that teacher and student are not subclasses of human, but rather are roles that a human can play. If you make them subclasses then you are effectively saying that teacher can never be a student and vice versa.
Also, if one goes from being a student to teacher (or vice versa) then you lose any associations and history for that object.
Consider roles instead. Consider composition and delegation instead of inheritance in this example.
Take a look at Peter Coad's book: Java Design for more on this.
Also, you do want to think about the table implementation if you do decide to use inheritance: single table (with null cols for the subtype attribs) separate table or single table for super class and separate tables for subclasses.

Hibernate has extensive support for different scenarios involving inheritance and polymorphism. See the documentation
http://docs.jboss.org/hibernate/stable/core/reference/en/html/inheritance.html
The short answer is, yes you can do exactly what you want -- create a base class with fields common to subclasses. How hard/involved it is depends on how you structure the tables.

Related

Making a simple UML class diagram for a school

I'm trying to create a simple class diagram for a school. Within my class-hierarchy, a school typically consist of two main stakeholders (student & teacher) and many students can be assigned to a teacher. May I know how I can show this relationship?
I have used aggregation and enumeration in my class diagram however, I'm not exactly sure if it's correct. Could you please advise me?
Multiplicity: The way you are using multiplicities is correct (as I can foresee it). It means that there must be at least one student per teacher. Without student, there is not teacher. Sounds like a hire and fire school with no permanent teachers.
Aggregation: You may use the shared aggregation (open diamond) the way you did. It's correct but see my remarks below.
Enumeration: Regarding the <<enumeration>> you would just need a dependency rather than an association. Unlike relations to classes an <<enumeration>> is kind of a "primitive" which is not represented as object.
Role names: As #Oguz points out it's a good idea to use role names at the end of the associations. So you would put teacher near Teacher and students (plural because you have 1..*) near Student at the association. These roles would be implemented as attributes.
Additional remarks on shared aggregation:
You must not care much about shared aggregation. As per UML specification it has no common semantics (p. 110 of UML 2.5):
Indicates that the Property has shared aggregation semantics. Precise semantics of shared aggregation varies by application area and modeler.
Aggregation is more about lifetime of objects and real life applications are rather rare than often (mainly if you have to be memory aware in terms of cost or security).
So in your (and most other) case(s) the multiplicity is what you want to show. This is usually more important than showing e.g. a composite aggregation (where the child objects dies with its parent) let alone shared composition.
You can change the aggregation name to students. And In the java code, teacher class has an array, arraylist or set etc. which name is students. And there is one more thing, is this relation 1 to many or 0 to many(0..*)?
public class Teacher extends StakeHolders{
public Student[] students;
public void markAttendance(){
}
}

Best approach for linking diverse entity types in JPA

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.

Fowler's Patterns: Dealing with table inheritance in a specific way

These days I'm reading Martin Fowler's Patterns of Enterprise Application Architecture, it's really great.
Since I kinda started an OO PHP project (app backend) I want to use Data Mapper for my Domain Model. I read about Table inheritance and I noticed there are 3 types of it.
I don't like Single because I will have more than few types of entries, which will be subclassed from the base class/type. In this case I would have lots of empty space in the db.
I don't see the other two being suitable either.
That is due to my plan of having:
Base class (Entry)
Subclass (example: StateInstitution extends Entry)
Subclass (example: CompanyAffiliate extends Entry)
....
The main point here is that I intend to be saving the extra info of the subclasses into a common table tbl_entrymeta - that is, I can have many subclasses that extend from the base Entry class, but not a separate table for each (just one, tbl_entrymeta).
My question is: How to use Data Mapper in this scenario? Is the key in creating inheritance mappers? Or metadata mappers are the key?
Create a Data Mapper class for the common table (EntryMeta) which represents the object of the relational database table tbl_entrymeta. This object will hold the meta of the subclasses within 3 Fields (columns):
1. SubClass
2. FieldName
3. FieldType
This way you can easily store the meta of all the sub-classes that inherit the base class and extend it with additional fields of information.

What is a good inheritance strategy with Hibernate and JPA?

I have this situation:
I have an entity, Person, that contains all personal details of a person, like birth date, street address, municipality ecc ecc.
And I have an entity ClubMember that describe a member of a club and contains some field like: registration date, type of member, credit, ecc ecc
So, a ClubMember is a Person, and I think is correct describe this with a inheritance:
ClubMember extends Person, but, what type of strategy?
I would obtain two table in database, Person and ClubMember, with ClubMember that contain id_person like an #OneToOne relationship, but keep the inheritance between entities; is this possible (and is correct)?
JOINED is the strategy closest to my target, but I lose the ID field of table ClubMember, in fact ID become the ID of table Person...
Blow, you should keep performance issues when choosing some kind of inheritance strategy. Here you can see a good insight about available inheritance strategies. Do not forget a inheritance can be re-writen as a association as follows
instead of
public class A {}
public class B extends A {}
you can use
public class B {
private A a;
}
Or you can use MapedSuperClass To map all of your inherited properties whitout using any Hibernate/JPA inheritance strategy. See here
Keep in mind when using default JPA/Hibernate annotations, Hibernate always fetch all of subclasses. If you have a single hierarchy, prefer To use Single Table Inheritance strategy. Joined strategy is better designed when you have a complex hierarchy but it suffers due To performance issues when querying for any entity.
EDIT: below answer assumed NHibernate, apologies beforehand if it doesn't apply to Hibernate
This is not always trivial, even it can be trivially implemented (see below), and should be considered thoroughly. In my experience, it's best to stick to good old aggregation, or even just fields, where each ClubMember has-a person, instead of is-a person. This may not entirely feel right, but it works easier with your configurations, the CRUD operations and your abstract DAO classes. Auto-mapping tools often don't support subclassing out of the box.
Also, people that work with both your database and the DAL, will have an understanding for this mapping (i.e., Person as a one-to-one mapping to ClubMember, add non-null to the Person-property and you have your constraint as well), because it resembles the database more closely. You may argue of course that the whole idea of ORM is to remove this similarity ;).
If you want to experiment on this path or if you like to see how it's done and apply it to your situation, Ayende has a nice blog on the subject of NHibernate and inheritance. It's a bit basic, but you'll get the idea. If you use Fluent NHibernate, it becomes a bit easier even, see this brief tutorial.
I would make ClubMemeber extend Person, as you suggested, and use the table per class heriarchy mapping strategy.
http://docs.jboss.org/hibernate/stable/core/reference/en/html/inheritance.html#inheritance-tableperclass

Hibernate Inheritance Mapping and Attribute Override

The system I'm working on has a domain object named Order which inherits from AbstractPersistentObject. Now I need to add another domain object named ExternalOrder which has some of the properties of Order but not all. I would like these two objects to be treated polimorphically in certain places. Hence I'm thinking of implementing inheritance mapping.
I've created an AbstractOrder which now extends AbstractPersistentObject and moved the common properties to AbstractOrder. Order and ExternalOrder now extends AbstractOrder.
Since the Order table already has lots of data in the database, I would prefer not to make too many changes to the schema.
If I omit InheritanceType.SINGLE_TABLE, which inheritance strategy would be better for me? I should mention I've to use OnetoMany join in at least one domain Object. The domain object would refer to AbstractOrder and Hibernate would decide at runtime the concrete subclass for this AbstractOrder.
AbstractPersistentObject has #Id and #GeneratedValue(strategy=GenerationType.IDENTITY) for the property id. Is there a way to override this when I implement inheritance? As I understand, GenerationType.IDENTITY is not going to work for certain inheritance choices and I'm not sure how to override this. I've looked into #AttributeOverride but I think it's only useful when you want to override certain #Column values.
1) You don't really have too many options here. Two other inheritance mapping strategies are table per class which won't work for you (as it doesn't support IDENTITY) and joined subclasses which will require you to split your "Orders" table into two (AbstractOrder and Order) plus add another table for ExternalOrder.
2) You can't override attributes on id within inheritance hierarchy. That's just as well, though, table-per-class strategy is definitely not ideal.

Categories