Enterprise Java Development@TOPIC@
Advantages
Can be normalized
Permits constraints to be defined
Disadvantages
Requires access to multiple tables when using (insert, select, update, and delete) an entity
More suitable for sub-classes that...
Have many unique properties
Require database constraints
Are queried for across sibling sub-types
Figure 65.2. Join Example Database Schema
create table ORMINH_PERSON ( id bigint generated by default as identity, firstName varchar(255), lastName varchar(255), primary key (id) ) create table ORMINH_EMPLOYEE ( hireDate date, payrate double not null, id bigint not null, primary key (id) ) alter table ORMINH_CUSTOMER add constraint FK6D5464A42122B7AC foreign key (id) references ORMINH_PERSON alter table ORMINH_EMPLOYEE add constraint FK9055CB742122B7AC foreign key (id) references ORMINH_PERSON
Table for each entity class is created
Each table has a primary key
Sub-class tables use a primary key join with parent class
Figure 65.3. Join Example Java Mapping (Parent Class)
@Entity @Table(name="ORMINH_PERSON")
@Inheritance(strategy=InheritanceType.JOINED)
public class Person {
@Id @GeneratedValue
private long id;
private String firstName;
private String lastName;
Parent defines default mapping for all derived types
Parent entity class table also defined
Figure 65.4. Join Example Java Mapping (Subclasses)
@Entity
@Table(name="ORMINH_CUSTOMER") //joined with Person table to form Customer
public class Customer extends Person {
public enum Rating { GOLD, SILVER, BRONZE }
@Enumerated(EnumType.STRING)
private Rating rating;
@Entity
@Table(name="ORMINH_EMPLOYEE") //joined with Person table to form Employee
public class Employee extends Person {
private double payrate;
@Temporal(TemporalType.DATE)
private Date hireDate;
Sub-classes define their entity-specific tables
Figure 65.5. Join Example Usage
ejava.examples.orm.inheritance.annotated.Employee employee = new Employee();
employee.setFirstName("john");
employee.setLastName("doe");
employee.setHireDate(new Date());
employee.setPayrate(10.00);
em.persist(employee);
ejava.examples.orm.inheritance.annotated.Customer customer = new Customer();
customer.setFirstName("jane");
customer.setLastName("johnson");
customer.setRating(Customer.Rating.SILVER);
em.persist(customer);
Hibernate: insert into ORMINH_PERSON (id, firstName, lastName) values (null, ?, ?) Hibernate: insert into ORMINH_EMPLOYEE (hireDate, payrate, id) values (?, ?, ?) Hibernate: insert into ORMINH_PERSON (id, firstName, lastName) values (null, ?, ?) Hibernate: insert into ORMINH_CUSTOMER (rating, id) values (?, ?)
Each persist() must insert into concrete class table and parent class table(s)
Figure 65.6. Join Example Usage (Get Entities)
List<Person> people = em.createQuery("select p from Person p", Person.class).getResultList();
assertTrue("unexpected number of people:" + people.size(),
people.size() == 2);
for(Person p: people) {
log.info("person found:" + p);
}
select person0_.id as id1_8_, person0_.firstName as firstNam2_8_, person0_.lastName as lastName3_8_, person0_1_.hireDate as hireDate1_6_, person0_1_.payrate as payrate2_6_, person0_2_.rating as rating1_5_, case when person0_1_.id is not null then 1 when person0_2_.id is not null then 2 when person0_.id is not null then 0 end as clazz_ from ORMINH_PERSON person0_ left outer join ORMINH_EMPLOYEE person0_1_ on person0_.id=person0_1_.id left outer join ORMINH_CUSTOMER person0_2_ on person0_.id=person0_2_.id -person found:Employee, id=1, firstName=john, lastName=doe, payrate=10.0 -person found:Customer, id=2, firstName=jane, lastName=johnson, rating=SILVER
Parent class table joined with each sub-class table during query of parent type
Figure 65.7. Join Example Usage (Verify DB Schema)
int rows = em.createNativeQuery(
"select ID, FIRSTNAME, LASTNAME from ORMINH_PERSON")
.getResultList().size();
assertEquals("unexpected number of person rows:" + rows, 2, rows);
rows = em.createNativeQuery(
"select ID, RATING from ORMINH_CUSTOMER")
.getResultList().size();
assertEquals("unexpected number of customer rows:" + rows, 1, rows);
rows = em.createNativeQuery(
"select ID, PAYRATE, HIREDATE from ORMINH_EMPLOYEE")
.getResultList().size();
assertEquals("unexpected number of employee rows:" + rows, 1, rows);
select * from ORMINH_PERSON ID FIRSTNAME LASTNAME -- --------- -------- 1 john doe 2 jane johnson select * from ORMINH_EMPLOYEE ID HIREDATE PAYRATE -- ---------- ------- 1 2006-10-08 10.0 select * from ORMINH_CUSTOMER ID RATING -- ------ 2 SILVER
Entities span multiple tables