Table per Concrete Class + Implicit Polymorphism
This is the technique with minimum development efforts. The technique follows the below simple steps:
The mapping files for the two tables is as below
The code on start up worked as normal, generating queries for both tables separately. Hibernate treated them just like any other mapping. Inserts of records in both tables were also the same.
Though it is very simple and easy, there exist certain problems with this approach:
Update: For a brief summary of the Hibernate Inheritance types check this post.
This is the technique with minimum development efforts. The technique follows the below simple steps:
- For each concrete class, one table is created.
- All the inherited properties are mapped in each of these tables.
- The abstract (base) class is not represented in SQL
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.inheritance.model"> <class name="Cricketer" table="CRICKETER"> <id name="id" type="long"> <column name="ID" /> <generator class="identity" /> </id> <property name="name" type="string"> <column name="NAME" /> </property> <property name="runs" type="integer"> <column name="RUNS" /> </property> <property name="wickets" type="integer"> <column name="WICKETS" /> </property> <property name="t20Player" type="boolean"> <column name="T20_PLAYER" /> </property> </class> </hibernate-mapping>
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.inheritance.model"> <class name="Footballer" table="FOOTBALLER"> <id name="id" type="long"> <column name="ID" /> <generator class="identity" /> </id> <property name="name" type="string"> <column name="NAME" /> </property> <property name="goals" type="integer"> <column name="GOALS" /> </property> <property name="appearances" type="integer"> <column name="APPEARANCES" /> </property> <property name="sendOffs" type="integer"> <column name="SEND_OFFS" /> </property> </class> </hibernate-mapping>
The code on start up worked as normal, generating queries for both tables separately. Hibernate treated them just like any other mapping. Inserts of records in both tables were also the same.
Though it is very simple and easy, there exist certain problems with this approach:
- Implementation of polymorphic associations: If we have to map the relation between Team and Sportsperson ( 1 team has many sportsperson) then we need to create a foreign key Team_Id in both the above tables. Similarly if we need to map relation between the players and fans (1 player has many fans) then the fan table would have to have two columns - CRICKETER_ID and FOOTBALL_ID. As number of such subclasses increase the columns will also increase.
- Execution of polymorphic queries:It is not possible to retrieve the values of all Sportsperson by direct query. Instead this can only be done via multiple select queries - one for Cricketers and one for footballers. I tried the same
public static void getAllSportsPerson() { Session session = sessionFactory.openSession(); try {//THIS WILL NEVER WORK Query query = session.createQuery("from SportsPerson"); System.out.println("Total Records : " + query.list().size()); } catch (HibernateException e) { e.printStackTrace(); } finally { session.close(); } }
The logs indicate the failure:
org.hibernate.hql.ast.QuerySyntaxException: SportsPerson is not mapped [from Spo rtsPerson] at org.hibernate.hql.ast.util.SessionFactoryHelper.requireClassPersister(Sessio nFactoryHelper.java:158) at org.hibernate.hql.ast.tree.FromElementFactory.addFromElement(FromElementFact ory.java:87) at org.hibernate.hql.ast.tree.FromClause.addFromElement(FromClause.java:70) at org.hibernate.hql.ast.HqlSqlWalker.createFromElement(HqlSqlWalker.java:255) at org.hibernate.hql.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3
- Property duplication: The name property which was inherited by both sub-classes now must be duplicated in both the created tables. Similarly, if we decide to add another attribute (e.g. date_of_birth) this would be a change in all the tables representing the sub-classes.
Update: For a brief summary of the Hibernate Inheritance types check this post.
No comments:
Post a Comment