Hi.
I'm trying to use EhCache, and it is really slow, much slower than not using cache.
I use the following classes:
Code:
@SuppressWarnings("serial")
@Entity
@Table(name="EMPLOYEE")
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
public class Employee {
private int id;
private String firstName;
private String lastName;
private Country country;
private Set<Language> languages;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="EMPLOYEE_ID")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="FIRST_NAME")
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
@Column(name="LAST_NAME")
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@ManyToOne
@JoinColumn(name="COUNTRY")
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
@Cascade(org.hibernate.annotations.CascadeType.ALL)
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
}
@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(joinColumns={@JoinColumn(name="EMPLOYEE_ID")},
inverseJoinColumns={@JoinColumn(name="LANGUAGE_ID")})
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
public Set<Language> getLanguages() {
return languages;
}
public void setLanguages(Set<Language> languages) {
this.languages = languages;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if ((obj == null) || (obj.getClass() != this.getClass()))
return false;
// object must be Player at this point
Employee test = (Employee) obj;
boolean result = this.id == test.id;
return result;
}
public int hashCode() {
return this.id;
}
Code:
@SuppressWarnings("serial")
@Entity
@Table(name="country")
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
public class Country {
private int id;
private String name;
private String printableName;
private String iso3;
private String iso;
private Set<Employee> employees;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="NUMCODE")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="printable_name")
public String getPrintableName() {
return printableName;
}
public void setPrintableName(String printableName) {
this.printableName = printableName;
}
@Column(name="iso")
public String getIso() {
return iso;
}
public void setIso(String iso) {
this.iso = iso;
}
@Column(name="iso3")
public String getIso3() {
return iso3;
}
public void setIso3(String iso3) {
this.iso3 = iso3;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if ((obj == null) || (obj.getClass() != this.getClass()))
return false;
// object must be Player at this point
Country test = (Country) obj;
boolean result = this.id == test.id;
return result;
}
public int hashCode() {
return this.id;
}
@OneToMany(targetEntity=Employee.class, mappedBy="country")
public Set<Employee> getEmployees() {
return employees;
}
public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
Code:
@SuppressWarnings("serial")
@Entity
@Table(name="LANGUAGE")
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
public class Language {
private int id;
private String name;
private Set<Employee> employees;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="LANGUAGE_ID")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if ((obj == null) || (obj.getClass() != this.getClass()))
return false;
// object must be Player at this point
Language test = (Language) obj;
boolean result = this.id == test.id;
return result;
}
public int hashCode() {
return this.id;
}
@ManyToMany(mappedBy="languages")
public Set<Employee> getEmployees() {
return employees;
}
public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
I'm using
Hibernate version: 3.2.5 MySQL 6The code that I use:
Code:
HibernateUtil.init();
long t0 = System.currentTimeMillis();
for(int i = 0; i < 500; i++) {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
List l = null;
l = session.createQuery("from Employee e where e.country=28").list();
tx.commit();
}
long t1 = System.currentTimeMillis();
System.out.println("Elapsed time = " + (t1 - t0) + " ms.");
The generated SQL:Hibernate: select employee0_.EMPLOYEE_ID as EMPLOYEE1_55_, employee0_.COUNTRY as COUNTRY55_, employee0_.FIRST_NAME as FIRST2_55_, employee0_.LAST_NAME as LAST3_55_ from EMPLOYEE employee0_ where employee0_.COUNTRY=28
Hibernate: select country0_.NUMCODE as NUMCODE56_0_, country0_.iso as iso56_0_, country0_.iso3 as iso3_56_0_, country0_.name as name56_0_, country0_.printable_name as printable5_56_0_ from country country0_ where country0_.NUMCODE=?
Hibernate: select languages0_.EMPLOYEE_ID as EMPLOYEE1_1_, languages0_.LANGUAGE_ID as LANGUAGE2_1_, language1_.LANGUAGE_ID as LANGUAGE1_54_0_, language1_.NAME as NAME54_0_ from EMPLOYEE_LANGUAGE languages0_ left outer join LANGUAGE language1_ on languages0_.LANGUAGE_ID=language1_.LANGUAGE_ID where languages0_.EMPLOYEE_ID=?
These queries are used only for the 1st iteration of the loop. After that all entities are found in the cache.
Debug level Hibernate log excerpt:15 Oct 2008 16:09:57,713 DEBUG EhCache:77 - key: com.BPIntech.playSPEX.core.businessLogic.entities.real.Country#28
15 Oct 2008 16:09:57,714 DEBUG MemoryStore:135 - com.BPIntech.playSPEX.core.businessLogic.entities.real.CountryCache: com.BPIntech.playSPEX.core.businessLogic.entities.real.CountryMemoryStore hit for com.BPIntech.playSPEX.core.businessLogic.entities.real.Country#28
15 Oct 2008 16:09:57,716 DEBUG EhCache:77 - key: com.BPIntech.playSPEX.core.businessLogic.entities.real.Employee.languages#3949
15 Oct 2008 16:09:57,717 DEBUG MemoryStore:135 - com.BPIntech.playSPEX.core.businessLogic.entities.real.Employee.languagesCache: com.BPIntech.playSPEX.core.businessLogic.entities.real.Employee.languagesMemoryStore hit for com.BPIntech.playSPEX.core.businessLogic.entities.real.Employee.languages#3949
15 Oct 2008 16:09:57,717 DEBUG EhCache:77 - key: com.BPIntech.playSPEX.core.businessLogic.entities.real.Language#17
15 Oct 2008 16:09:57,723 DEBUG MemoryStore:135 - com.BPIntech.playSPEX.core.businessLogic.entities.real.LanguageCache: com.BPIntech.playSPEX.core.businessLogic.entities.real.LanguageMemoryStore hit for com.BPIntech.playSPEX.core.businessLogic.entities.real.Language#17
15 Oct 2008 16:09:57,724 DEBUG EhCache:77 - key: com.BPIntech.playSPEX.core.businessLogic.entities.real.Language#16
15 Oct 2008 16:09:57,724 DEBUG MemoryStore:135 - com.BPIntech.playSPEX.core.businessLogic.entities.real.LanguageCache: com.BPIntech.playSPEX.core.businessLogic.entities.real.LanguageMemoryStore hit for com.BPIntech.playSPEX.core.businessLogic.entities.real.Language#16
15 Oct 2008 16:09:57,726 DEBUG EhCache:77 - key: com.BPIntech.playSPEX.core.businessLogic.entities.real.Language#9
15 Oct 2008 16:09:57,727 DEBUG MemoryStore:135 - com.BPIntech.playSPEX.core.businessLogic.entities.real.LanguageCache: com.BPIntech.playSPEX.core.businessLogic.entities.real.LanguageMemoryStore hit for com.BPIntech.playSPEX.core.businessLogic.entities.real.Language#9
continued by many more ...
Hibernate Configuration:hibernate.connection.url = jdbc:mysql://localhost/testing?autoReconnect=true
hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
hibernate.connection.pool_size = 3
hibernate.current_session_context_class = thread
hibernate.connection.autocommit = false
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=50
# hibernate 2nd cache
hibernate.cache.use_second_level_cache=true
hibernate.cache.provider_class=net.sf.ehcache.hibernate.SingletonEhCacheProvider
net.sf.ehcache.configurationResourceName=/ehcache2.xml
hibernate.cache.use_query_cache=true
EhCache configuration: <defaultCache
maxElementsInMemory="50000"
eternal="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
<cache name="com.BPIntech.playSPEX.core.businessLogic.entities.real.Employee"
maxElementsInMemory="5000"
eternal="true"
overflowToDisk="false"
/>
<cache name="com.BPIntech.playSPEX.core.businessLogic.entities.real.Language"
maxElementsInMemory="100"
eternal="true"
overflowToDisk="false"
/>
<cache name="com.BPIntech.playSPEX.core.businessLogic.entities.real.Country"
maxElementsInMemory="500"
eternal="true"
overflowToDisk="false"
/>
<cache name="com.BPIntech.playSPEX.core.businessLogic.entities.real.Employee.languages"
maxElementsInMemory="40000"
eternal="true"
overflowToDisk="false"
/>
<cache name="com.BPIntech.playSPEX.core.businessLogic.entities.real.Employee.country"
maxElementsInMemory="5000"
eternal="true"
overflowToDisk="false"
/>
<cache name="org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="5000"
eternal="true"
timeToLiveSeconds="120"
overflowToDisk="false"
/>
<cache name="org.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="50000"
eternal="true"
overflowToDisk="false"
/>
Any would be highly appreciated.
Regards,
Amir[/code]