Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Java Persistence’s TABLE_PER_CLASS Is Evil

DZone's Guide to

Java Persistence’s TABLE_PER_CLASS Is Evil

If you use the TABLE_PER_CLASS inheritance strategy, your database performance will be dragged down as the data grows. Switching to JOINED is a good idea.

· Database Zone
Free Resource

Traditional relational databases weren’t designed for today’s customers. Learn about the world’s first NoSQL Engagement Database purpose-built for the new era of customer experience.

The TABLE_PER_CLASS inheritance strategy uses some of the most inefficient ways to query. Your database performance will be dragged down as the data grows. Consider switching to JOINED.

Slow Performance Explained

Consider a simple entity hierarchy: ParentClass, ChildClassA, and ChildClassB.

@Entity
@InheritanceStrategy(TABLE_PER_CLASS)
public class ParentClass {
  @Id
  public Int id;
  /* excluding extra code for verbosity */
}

@Entity
@Table(“child_a”)
public class ChildClassA { … }

@Entity
@Table(“child_b”)
public class ChildClassB { … }

Calling a simple em.find(ParentClass.class, id) would make Hibernate generate the following native query:

(SELECT _a.id, … FROM child_a AS _a 
 UNION 
 SELECT _b.id, … FROM AS _b) 
 WHERE id = ‘…’;

You might have realized there are two fundamental flaws with this query:

  1. All of the table’s data is loaded-absolutely critical to keep in mind, especially when tables have millions of records or when there is a more complex hierarchy at play.
  2. Since the criteria is done on the absolute collective of the tables, all of the indices which the tables have are completely unused. Even worse, the criteria are now working against no indices!

Using JOINED as a Solution

One way to go around this is by changing the inheritance strategy to JOINED, which essentially introduces the third, parent table: parent.

Calling em.find(ParentClass.class, id) generates a far more optimized query:

SELECT _p.id, ...,        _a.id, ...,        _b.id, ...   
  FROM parent AS _p   
  INNER JOIN child_a AS _a on _p.id=_a.id   
  INNER JOIN child_b AS _b on _p.id=_b.id 
  WHERE _p.id= '...';

Joining on the table’s own primary keys would link the tables together more optimal, allowing for faster querying.

That’s all I have to say! Do you have another alternative you would like to share or a justification on when to use TABLE_PER_CLASS? We’d be happy to know in the comments below!

Learn how the world’s first NoSQL Engagement Database delivers unparalleled performance at any scale for customer experience innovation that never ends.

Topics:
performance ,database performance ,joined

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}