15.1 Overview
In the previous chapter, we discussed persistence of parent and child relations and we did highlight the point of additional code, that has been written to save the child object. However the parent class should handle it internally. In this chapter, we will discuss the cascading the object state and different fetching strategies that can be used to improve the performance.
15.2 Cascading Object State
The whole concept of parent child relationship is that one object should take care of persistence of another object internally and application programmer need not write additional code to manage the persistence. In chapter 14 we saw that we need to explicitly call save operation on both stadium and on cricketmatch like below
Stadium stadium = new Stadium(); stadium.setCapacity(2300); stadium.setCountry("Australia"); stadium.setName("Sydney"); CricketMatch match = new CricketMatch(); match.setTeam1("India"); match.setTeam2("Australia"); match.setType("Test Match"); match.setUmpire("Billy Bowden"); match.setStadium(stadium); session.save(stadium); session.save(match);
Hibernate provides an option “cascade” which offers several options to handle such scenarios.
We will use below hibernate.cfg.xml in this entire chapter
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.url"> jdbc:mysql://localhost:3306/tutorial </property> <property name="hibernate.connection.username"> root </property> <property name="hibernate.connection.password"> password </property> <property name="dialect"> org.hibernate.dialect.MySQLDialect </property> <property name="hibernate.format_sql">true</property> <property name="show_sql">true</property> <property name="hibernate.connection.driver_class"> com.mysql.jdbc.Driver </property> <mapping resource="association-mapping.hbm.xml" /> </session-factory> </hibernate-configuration>
15.2.1 Scenario
We will take a scenario of One to Many association between Stadium and Cricket Match. One stadium can host many cricket matches is the one to many association from Stadium end.
Let’s design our Entity classes which we will use in the entire chapter
CricketMatch.java
package com.tutorial.hibernate; public class CricketMatch { private int id; private String team1; private String team2; private String umpire; private String type; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTeam1() { return team1; } public void setTeam1(String team1) { this.team1 = team1; } public String getTeam2() { return team2; } public void setTeam2(String team2) { this.team2 = team2; } public String getUmpire() { return umpire; } public void setUmpire(String umpire) { this.umpire = umpire; } public String getType() { return type; } public void setType(String type) { this.type = type; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + id; result = prime * result + ((team1 == null) ? 0 : team1.hashCode()); result = prime * result + ((team2 == null) ? 0 : team2.hashCode()); result = prime * result + ((type == null) ? 0 : type.hashCode()); result = prime * result + ((umpire == null) ? 0 : umpire.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; CricketMatch other = (CricketMatch) obj; if (id != other.id) return false; if (team1 == null) { if (other.team1 != null) return false; } else if (!team1.equals(other.team1)) return false; if (team2 == null) { if (other.team2 != null) return false; } else if (!team2.equals(other.team2)) return false; if (type == null) { if (other.type != null) return false; } else if (!type.equals(other.type)) return false; if (umpire == null) { if (other.umpire != null) return false; } else if (!umpire.equals(other.umpire)) return false; return true; } @Override public String toString() { return "CricketMatch [id=" + id + ", team1=" + team1 + ", team2=" + team2 + ", umpire=" + umpire + ", type=" + type + "]"; } }
Stadium.java
package com.tutorial.hibernate; import java.util.HashSet; import java.util.Set; public class Stadium { private int id; private String name; private String country; private int capacity; private Set<CricketMatch> matches= new HashSet<CricketMatch>(); public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public int getCapacity() { return capacity; } public void setCapacity(int capacity) { this.capacity = capacity; } public Set<CricketMatch> getMatches() { return matches; } public void setMatches(Set<CricketMatch> matches) { this.matches = matches; } @Override public String toString() { return "Stadium [id=" + id + ", name=" + name + ", country=" + country + ", capacity=" + capacity + "]"; } }
Create Table Scripts
CREATE TABLE 'stadium' ( 'stadium_id' int(11) NOT NULL AUTO_INCREMENT, 'stadium_name' varchar(255) DEFAULT NULL, 'capacity' int(11) DEFAULT NULL, 'country' varchar(255) DEFAULT NULL, PRIMARY KEY ('stadium_id') ); CREATE TABLE 'cricket_match' ( 'match_id' int(11) NOT NULL AUTO_INCREMENT, 'team1' varchar(255) DEFAULT NULL, 'team2' varchar(255) DEFAULT NULL, 'type' varchar(255) DEFAULT NULL, 'umpire' varchar(255) DEFAULT NULL, 'stadium_id' int(11) DEFAULT NULL, PRIMARY KEY ('match_id'), KEY 'FK' ('stadium_id'), CONSTRAINT 'FK_70fxuvas8xraq7mo6rpmsekxx' FOREIGN KEY ('stadium_id') REFERENCES 'stadium' ('stadium_id') );