Question :
=========
I have a simple Country/State/City model. A country has a collection of states that in return has a collection of cities.
With the following code which simply accesses a specific country ('CA') and navigate among its states and cities :
/**
* Test
*/
public static void main(String[] args) {
long start;
for (int i=0; i<10; i++) {
Session session = HibernateUtil.getSession();
Country country = session.get(Country.class, "CA");
HibernateUtil.closeSession();
State state;
for(Iterator iter = country.getStates().iterator(); iter.hasNext();) {
state = (State) iter.next();
for(Iterator iter2 = state.getCities().iterator(); iter2.hasNext();) {
((City) iter2.next()).getCode();
}
}
}
...the second level cache does not seem to be hit. I can see selects being sent to the database if I try multiple accesses to the same country (code='CA').
What am I missing?
DB Schema :
=========
create table COUNTRY (
CODE varchar(50) not null,
VERSION integer not null,
NAME varchar(50) not null,
primary key (CODE)
);
create table STATE (
CODE varchar(50) not null,
VERSION integer not null,
NAME varchar(50) not null,
COUNTRY_ID varchar(50) not null,
primary key (CODE)
);
create table CITY (
CODE varchar(50) not null,
VERSION integer not null,
NAME varchar(50) not null,
STATE_ID varchar(50) not null,
primary key (CODE)
);
Hibernate configuration :
===============
<property name="show_sql">true</property>
<!-- Second level cache -->
<property name="hibernate.cache.provider_class">net.sf.ehcache.hibernate.Provider</property>
<!-- Mapping files -->
<mapping resource="ca/kafeine/test/model/Country.hbm.xml"/>
<mapping resource="ca/kafeine/test/model/State.hbm.xml"/>
<mapping resource="ca/kafeine/test/model/City.hbm.xml"/>
EHCache configuration :
===============
<cache name="ca.kafeine.test.model.Country"
maxElementsInMemory="500"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<cache name="ca.kafeine.test.model.Country.states"
maxElementsInMemory="500"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<cache name="ca.kafeine.test.model.State"
maxElementsInMemory="500"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<cache name="ca.kafeine.test.model.State.cities"
maxElementsInMemory="500"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<cache name="ca.kafeine.test.model.City"
maxElementsInMemory="500"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
POJOs :
====
// Country
package ca.kafeine.test.model;
import java.io.Serializable;
import java.util.Set;
import org.apache.commons.lang.builder.ToStringBuilder;
/** @author Hibernate CodeGenerator */
public class Country implements Serializable, Comparable {
/** identifier field */
private String code;
/** persistent field */
private String nom;
/** nullable persistent field */
private Integer version;
/** persistent field */
private Set provincesEtats;
/** full constructor */
public Country(String code, String nom, Integer version, Set provincesEtats) {
this.code = code;
this.nom = nom;
this.version = version;
this.provincesEtats = provincesEtats;
}
/** default constructor */
public Country() {
}
/** minimal constructor */
public Country(String code, String nom, Set provincesEtats) {
this.code = code;
this.nom = nom;
this.provincesEtats = provincesEtats;
}
public String getCode() {
return this.code;
}
public void setCode(String code) {
this.code = code;
}
public String getNom() {
return this.nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public Integer getVersion() {
return this.version;
}
public void setVersion(Integer version) {
this.version = version;
}
public Set getStates() {
return this.provincesEtats;
}
public void setStates(Set provincesEtats) {
this.provincesEtats = provincesEtats;
}
public String toString() {
return new ToStringBuilder(this)
.append("code", getCode())
.toString();
}
public boolean equals(Object obj) {
if (obj instanceof Country) {
Country pe = (Country) obj;
return pe.code.equals(this.code);
}
return false;
}
public int compareTo(Object obj) {
if (obj instanceof Country) {
Country pe = (Country) obj;
return pe.code.compareTo(this.code);
}
return 0;
}
}
// State
package ca.kafeine.test.model;
import java.io.Serializable;
import java.util.Set;
import org.apache.commons.lang.builder.ToStringBuilder;
/** @author Hibernate CodeGenerator */
public class State implements Serializable, Comparable {
/** identifier field */
private String code;
/** persistent field */
private String nom;
/** nullable persistent field */
private Integer version;
/** persistent field */
private ca.kafeine.test.model.Country pays;
/** persistent field */
private Set villes;
/** full constructor */
public State(String code, String nom, Integer version, ca.kafeine.test.model.Country pays, Set villes) {
this.code = code;
this.nom = nom;
this.version = version;
this.pays = pays;
this.villes = villes;
}
/** default constructor */
public State() {
}
/** minimal constructor */
public State(String code, String nom, ca.kafeine.test.model.Country pays, Set villes) {
this.code = code;
this.nom = nom;
this.pays = pays;
this.villes = villes;
}
public String getCode() {
return this.code;
}
public void setCode(String code) {
this.code = code;
}
public String getNom() {
return this.nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public Integer getVersion() {
return this.version;
}
public void setVersion(Integer version) {
this.version = version;
}
public ca.kafeine.test.model.Country getCountry() {
return this.pays;
}
public void setCountry(ca.kafeine.test.model.Country pays) {
this.pays = pays;
}
public Set getCities() {
return this.villes;
}
public void setCities(Set villes) {
this.villes = villes;
}
public String toString() {
return new ToStringBuilder(this)
.append("code", getCode())
.toString();
}
public boolean equals(Object obj) {
if (obj instanceof State) {
State pe = (State) obj;
return pe.code.equals(this.code);
}
return false;
}
public int compareTo(Object obj) {
if (obj instanceof State) {
State pe = (State) obj;
return pe.code.compareTo(this.code);
}
return 0;
}
}
// City
package ca.kafeine.test.model;
import java.io.Serializable;
import org.apache.commons.lang.builder.ToStringBuilder;
/** @author Hibernate CodeGenerator */
public class City implements Serializable, Comparable {
/** identifier field */
private String code;
/** persistent field */
private String nom;
/** nullable persistent field */
private Integer version;
/** persistent field */
private ca.kafeine.test.model.State provinceEtat;
/** full constructor */
public City(String code, String nom, Integer version, ca.kafeine.test.model.State provinceEtat) {
this.code = code;
this.nom = nom;
this.version = version;
this.provinceEtat = provinceEtat;
}
/** default constructor */
public City() {
}
/** minimal constructor */
public City(String code, String nom, ca.kafeine.test.model.State provinceEtat) {
this.code = code;
this.nom = nom;
this.provinceEtat = provinceEtat;
}
public String getCode() {
return this.code;
}
public void setCode(String code) {
this.code = code;
}
public String getNom() {
return this.nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public Integer getVersion() {
return this.version;
}
public void setVersion(Integer version) {
this.version = version;
}
public ca.kafeine.test.model.State getState() {
return this.provinceEtat;
}
public void setState(ca.kafeine.test.model.State provinceEtat) {
this.provinceEtat = provinceEtat;
}
public String toString() {
return new ToStringBuilder(this)
.append("code", getCode())
.toString();
}
public boolean equals(Object obj) {
if (obj instanceof City) {
City pe = (City) obj;
return pe.code.equals(this.code);
}
return false;
}
public int compareTo(Object obj) {
if (obj instanceof City) {
City pe = (City) obj;
return pe.code.compareTo(this.code);
}
return 0;
}
}
Hibernate version:
2.1.6
Mapping documents:
<!-- Country entity -->
<hibernate-mapping>
<class name="ca.kafeine.test.model.Country"
mutable="false"
table="COUNTRY">
<cache usage="read-only"/>
<id name="code"
column="CODE"
type="string"
length="50">
<generator class="assigned"/>
</id>
<version name="version"
column="VERSION"
type="integer" />
<property name="name"
column="NAME"
type="string"
not-null="true"
length="50">
</property>
<set name="states"
inverse="true"
lazy="false"
cascade="all-delete-orphan">
<key column="COUNTRY_ID" />
<one-to-many class="ca.kafeine.test.model.State" />
</set>
</class>
</hibernate-mapping>
<!-- State entity -->
<hibernate-mapping>
<class name="ca.kafeine.test.model.State"
mutable="false"
table="STATE">
<cache usage="read-only"/>
<id name="code"
column="CODE"
type="string"
length="50">
<generator class="assigned"/>
</id>
<version name="version"
column="VERSION"
type="integer" />
<property name="name"
column="NAME"
type="string"
not-null="true"
length="50">
</property>
<many-to-one name="country"
column="COUNTRY_ID"
class="ca.kafeine.test.model.Country"
not-null="true"/>
<set name="cities"
inverse="true"
lazy="false"
cascade="all-delete-orphan">
<key column="STATE_ID" />
<one-to-many class="ca.kafeine.test.model.City" />
</set>
</class>
</hibernate-mapping>
<!-- City entity -->
<hibernate-mapping>
<class name="ca.kafeine.test.model.City"
mutable="false"
table="CITY">
<cache usage="read-only"/>
<id name="code"
column="CODE"
type="string"
length="50">
<generator class="assigned"/>
</id>
<version name="version"
column="VERSION"
type="integer" />
<property name="name"
column="NAME"
type="string"
not-null="true"
length="50">
</property>
<many-to-one name="state"
column="STATE_ID"
class="ca.kafeine.test.model.State"
not-null="true"/>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():
Country country = session.get(Country.class, "CA");
Full stack trace of any exception that occurs:
NIL
Name and version of the database you are using:
PointBase Server Version: 4.8RE
The generated SQL (show_sql=true):
Debug level Hibernate log excerpt:
|