Flanging edge because I also learn, there is nothing inevitable place undue Translations are welcome to U.S. criticism
Original Title: Speed Up Your Hibernate Application with Second-Level Caching
Original Source: http://www.devx.com/dbzone/Article/29685/1954
About the author: John Ferguson Smart, who took part in a lot of business and government of large-scale J2EE projects, his expertise includes the J2EE architecture, development and IT project management. He also has a lot of open source in JAVA technology experience. This is his blog links to technical www.jroller.com / page / wakaleo
Translate the original as follows:
Through the secondary cache to speed up your hibernate application
New hibernate developers sometimes do not know the results of hibernate cache has not fully use it, in spite of this, when we correct use of cache, it can hibernate to speed up the application, one of the most powerful weapon.
In web applications and large data volume of the database interaction often leads to performance issues. hibernate is a high performance, and provide object / relational persistence and query service, but if you do not help will not solve all performance problems. In many cases, the secondary cache is hibernate potential to achieve all the required performance on the deal. This article will examine the cache hibernate feature and show how to use can be significantly improved application performance.
Introduction cache
Caching is widely used in database applications. Cache design is the adoption of storage in order to have data read from the database to reduce the application and database data flow, and database access to retrieve the data only in the cache is not present when required. If the database to a number of ways to update and modify, then the application may need to periodically empty the cache, because it is no way to know the data cache are not up to date.
Hibernate Cache
Run from the object, hibernate cache using two methods: a cache and secondary cache. Session cache and an object, the secondary cache and Session Factory object. By default, hibernate caching level to use as a foundation Affairs pretreatment. hibernate to use it mainly in order to reduce the time to set matters need to be generated SQL query. For example, an object in the same affairs been modified several times, hibernate will be at the end of the Services only to generate an SQL update statement, it encompasses all the changes. This article introduces two cache. And databases in order to reduce interactive, secondary cache to preserve the object has been read out in all matters between the Session Factory level. These objects in the entire process can be, and not just when the user to run queries. In this way, return the object of each inquiry have been included in the cache, one or more database transactions potentially could have been avoided.
In addition, you can use the query cache if you need to level cache actual query results, not just the persistent object.
Cache implementation
Cache are part of the complexity of software, the market also provides a considerable number of options, including those based on open source and commercial. hibernate provided the following open-source implementation of the cache, as follows:
* EHCache (org.hibernate.cache.EhCacheProvider)
* OSCache (org.hibernate.cache.OSCacheProvider)
* SwarmCache (org.hibernate.cache.SwarmCacheProvider)
* JBoss TreeCache (org.hibernate.cache.TreeCacheProvider)
Provides a different cache in terms of performance, memory usage and configuration of the scalable capacity of different
EHCache is a fast, lightweight, easy-to-use cache. It supports read-only and read-write cache, memory and hard disk-based data storage. However, it does not support clusters.
OSCache is another open-source caching solution for it is a jsp page and arbitrary object cache function to provide a large part of the development kit. It itself is a powerful and flexible development kit, such as the same EHCache, and also supports read-only and read-write cache, memory and hard disk-based data storage. It JavaGroups or JMS also provides basic support for the cluster.
SwarmCache is a cluster-based solution, it is also based on the Inter-Entity Communication Services cluster communication protocol. It provides a read-only and no limit to read and write cache (the next section will explain this term). This type of cache for those who read the typical operation of write operations than many of the many applications that are suitable.
JBoss TreeCache is a powerful duality (synchronous or asynchronous) and transactional cache. Use this implementation if you really need a servicing capacity of the cache architecture.
Another worth mentioning is the commercial implementation of the cache of the Tangosol Coherence cache.
Cache strategy
Once you select a cache you realize, you need to specify the caching strategy for you. The following is a cache of four strategies:
Read-only: This strategy of the kind of data is frequently read but not updated to be effective, this is by far the simplest, best performing cache strategy.
Reading and writing: read and write cache on the assumption that the data you need to update is necessary. But reading and writing required to spend more than the read-only cache resources. At the affairs of non-JTA environments, each required to complete a transaction at Session.close () or Session.disconnect () is called time.
There is no limit of the read and write: This strategy can not guarantee that two matters will not simultaneously modify the same data. Therefore, it may be to those data are often read but only occasionally write operation to the most suitable.
Affairs: this is a fully transactional cache, it may only be used in JTA environments.
For each cache implementation, the support strategies are not unique. Figure 1 shows the
Cache implementation available for choice.
The remaining part of article used to show a use of a single JVM cache EHCache.
Cache configuration
In order to enable the secondary cache, we need to hibernate.cfg.xml configuration file hibernate.cache.provider_class definition of property, as
Java code
1. <hibernate-configuration>
2. <session-factory>
3. ...
4. <property Name="hibernate.cache.provider_class">
5. Org.hibernate.cache.EHCacheProvider
6. </ Property>
7. ...
8. </ Session-factory>
9. </ Hibernate-configuration>
<hibernate-configuration>
<session-factory>
...
<property name="hibernate.cache.provider_class">
org.hibernate.cache.EHCacheProvider
</ property>
...
</ session-factory>
</ hibernate-configuration>
Hibernate3 for test at the end, you have to use hibernate.cache.use_second_level_cache property, which allows you the opening (and closing) the secondary cache. By default, the secondary cache is enabled at the same time EHCache.
A practical application
This example demonstrated a simple process consists of four tables: a list of country, the airport list, staff list, language list. Each employee was assigned a country and can say a lot of language. Each country can have any number of airports.
Figure 1 shows the UML Class Diagram
Figure Two shows the database architecture
This example source code (http://assets.devx.com/sourcecode/14239.tgz) include the following SQL script, you need to use it to create and instantiate database.
* Src / sql / create.sql: create database SQL script
* Src / sql / init.sql: test data
Maven2 installation
Writing at the time, Maven2 installation directory appears as if the lack of a number of jars. To solve this problem, in the application source code to find the root of the lack of those jars. Put them to install the Maven2 document to the application directory, execute the following command
$ Mvn install: install-file-DgroupId = javax.security-DartifactId = jacc
-Dversion = 1.0
-Dpackaging = jar-Dfile = jacc-1.0.jar
$ Mvn install: install-file-DgroupId = javax.transaction-DartifactId = jta-Dversion = 1.0.1B
-Dpackaging = jar-Dfile = jta-1.0.1B.jar
Set up a read-only cache
From simple start, the following country are kind of hibernate mapping.
Java code
1. <hibernate-mapping Package="com.wakaleo.articles.caching.businessobjects">
2. <class Name="Country" table="COUNTRY" dynamic-update="true">
3. <meta Attribute="implement-equals"> true </ meta>
4. <cache Usage="read-only"/>
5.
6. <id Name="id" type="long" unsaved-value="null">
7. <column Name="cn_id" not-null="true"/>
8. <generator/>
9. </ Id>
10.
11. <property Column="cn_code" name="code" type="string"/>
12. <property Column="cn_name" name="name" type="string"/>
13.
14. <set Name="airports">
15. <key Column="cn_id"/>
16. <one-to-many/>
17. </ Set>
18. </ Class>
19. </ Hibernate-mapping>
<hibernate-mapping package="com.wakaleo.articles.caching.businessobjects">
<class name="Country" table="COUNTRY" dynamic-update="true">
<meta attribute="implement-equals"> true </ meta>
<cache usage="read-only"/>
<id name="id" type="long" unsaved-value="null">
<column name="cn_id" not-null="true"/>
<generator/>
</ id>
<property column="cn_code" name="code" type="string"/>
<property column="cn_name" name="name" type="string"/>
<set name="airports">
<key column="cn_id"/>
<one-to-many/>
</ set>
</ class>
</ hibernate-mapping>
Suppose you want to show the country list. CountryDAO you can type in a simple way to achieve, as
Java code
1. Public class CountryDAO (
2. ...
3. Public List getCountries () (
4. Return SessionManager.currentSession ()
5.. CreateQuery (
6. "From Country as c order by c.name")
7.. List ();
8.)
9.)
public class CountryDAO (
...
public List getCountries () (
return SessionManager.currentSession ()
. createQuery (
"from Country as c order by c.name")
. list ();
)
)
Since this method has often been called, so you need to know its behavior under stress. Writing a simple unit testing to simulate the 5 consecutive calls.
Java code
1. Public void testGetCountries () (
2. CountryDAO dao = new CountryDAO ();
3. For (int i = 1; i <= 5; i + +) (
4. Transaction tx = SessionManager.getSession (). BeginTransaction ();
5. TestTimer timer = new TestTimer ( "testGetCountries");
6. List countries = dao.getCountries ();
7. Tx.commit ();
8. SessionManager.closeSession ();
9. Timer.done ();
10. AssertNotNull (countries);
11. AssertEquals (countries.size (), 229);
12.)
13.)
public void testGetCountries () (
CountryDAO dao = new CountryDAO ();
for (int i = 1; i <= 5; i + +) (
Transaction tx = SessionManager.getSession (). BeginTransaction ();
TestTimer timer = new TestTimer ( "testGetCountries");
List countries = dao.getCountries ();
tx.commit ();
SessionManager.closeSession ();
timer.done ();
assertNotNull (countries);
assertEquals (countries.size (), 229);
)
)
You can run this test through your favorite IDE or command line Maven2 (demo provides two Maven2 project files). This demo program through the local mysql to test. When you run this test, it should be similar to the following information:
$ mvn test-Dtest = CountryDAOTest
...
testGetCountries: 521 ms.
testGetCountries: 357 ms.
testGetCountries: 249 ms.
testGetCountries: 257 ms.
testGetCountries: 355 ms.
[surefire] Running com.wakaleo.articles.caching.dao.CountryDAOTest
[surefire] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 3504 sec
We can see that each call to spend approximately half a second of time, for most standards is still somewhat slow. Country list is not always possible changes, so this class can be used as read-only cache a good candidate. So go add
You can enable the secondary cache with the following two methods of any one of
1. *. Hbm.xml you can enable it in, use the property cache
Java code
1. <hibernate-mapping Package="com.wakaleo.articles.caching.businessobjects">
2. <class Name="Country" table="COUNTRY" dynamic-update="true">
3. <meta Attribute="implement-equals"> true </ meta>
4. <cache Usage="read-only"/>
5. ...
6. </ Class>
7. </ Hibernate-mapping>
<hibernate-mapping package="com.wakaleo.articles.caching.businessobjects">
<class name="Country" table="COUNTRY" dynamic-update="true">
<meta attribute="implement-equals"> true </ meta>
<cache usage="read-only"/>
...
</ class>
</ hibernate-mapping>
2. You can store all the cached information in the hibernate.cfg.xml file, use the class-cache property
Java code
1. <hibernate-configuration>
2. <session-factory>
3. ...
4. <property Name="hibernate.cache.provider_class">
5. Org.hibernate.cache.EHCacheProvider
6. </ Property>
7. ...
8. <Class-cache
9.
10. Usage = "read-only"
11. />
12. </ Session-factory>
13. </ Hibernate-configuration>
<hibernate-configuration>
<session-factory>
...
<property name="hibernate.cache.provider_class">
org.hibernate.cache.EHCacheProvider
</ property>
...
<class-cache
class = "com.wakaleo.articles.caching.businessobjects.Country"
usage = "read-only"
/>
</ session-factory>
</ hibernate-configuration>
Next, you need to set up this type of cache rules decide how the performance of a cache details. This example is the use of demonstration EHCache, but remember that each type of cache implementation is not the same.
EHCache need a configuration file (usually called ehcache.xml) category at the root directory. Configuration file EHCache detailed documentation can be seen here (http://ehcache.sourceforge.net/documentation). Basically, you want to cache required for each class definition rules, as well as a defaultCache you are not clearly identified at any of the rules give a class to use when.
The first example, you can use the following simple configuration file EHCache
Java code
1. <ehcache>
2.
3. <diskStore Path="java.io.tmpdir"/>
4.
5. <DefaultCache
6. MaxElementsInMemory = "10000"
7. Eternal = "false"
8. TimeToIdleSeconds = "120"
9. TimeToLiveSeconds = "120"
10. OverflowToDisk = "true"
11. DiskPersistent = "false"
12. DiskExpiryThreadIntervalSeconds = "120"
13. MemoryStoreEvictionPolicy = "LRU"
14. />
15.
16. <Cache name = "com.wakaleo.articles.caching.businessobjects.Country"
17. MaxElementsInMemory = "300"
18. Eternal = "true"
19. OverflowToDisk = "false"
20. />
21.
22. </ Ehcache>
<ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory = "10000"
eternal = "false"
timeToIdleSeconds = "120"
timeToLiveSeconds = "120"
overflowToDisk = "true"
diskPersistent = "false"
diskExpiryThreadIntervalSeconds = "120"
memoryStoreEvictionPolicy = "LRU"
/>
<cache name = "com.wakaleo.articles.caching.businessobjects.Country"
maxElementsInMemory = "300"
eternal = "true"
overflowToDisk = "false"
/>
</ ehcache>
The document type for the countries set up a maximum of 300 units based on the memory cache (countries category includes 229 countries). Attention to the cache do not expire ( 'eternal = true' property). Now return the results through the performance of cache facie
$ mvn test-Dtest = CompanyDAOTest
...
testGetCountries: 412 ms.
testGetCountries: 98 ms.
testGetCountries: 92 ms.
testGetCountries: 82 ms.
testGetCountries: 93 ms.
[surefire] Running com.wakaleo.articles.caching.dao.CountryDAOTest
[surefire] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 2823 sec
As you look out, first query did not change because of the need to load data. However, several subsequent inquiries more quickly.
Backgrounds
Before we continue, before what happened Backgrounds facie very useful. One thing you need to know are not stored in cache hibernate object instance, instead of it stored object "dehydrated" form (hibernate the terminology), that is, as a series of property values. The following countries are an example of the contents of the cache
(
30 => [bw, Botswana, 30],
214 => [uy, Uruguay, 214],
158 => [pa, Panama, 158],
31 => [by, Belarus, 31]
95 => [in, India, 95]
...
)
Note that each ID is, how a property value is mapped to the owner of the array. You probably also noticed that only the main property was stored, but not airports property, airports This is because property is just a correlation: the other a series of persistent object references.
By default, hibernate is not associated cache. By which you decide to cache link, which link needs to be overloaded when the cache object from the secondary cache access time.
Associated cache is a very powerful functions. The next section we will introduce more content.
And associated cache to work with
Assuming you need to display a given country to all staff (including staff name, the language used, etc.). The following is a kind of hibernate mapping employee
Java code
1. <hibernate-mapping Package="com.wakaleo.articles.caching.businessobjects">
2. <class Name="Employee" table="EMPLOYEE" dynamic-update="true">
3. <meta Attribute="implement-equals"> true </ meta>
4.
5. <id Name="id" type="long" unsaved-value="null">
6. <column Name="emp_id" not-null="true"/>
7. <generator/>
8. </ Id>
9.
10. <property Column="emp_surname" name="surname" type="string"/>
11. <property Column="emp_firstname" name="firstname" type="string"/>
12.
13. <Many-to-one name = "country"
14. Column = "cn_id"
15.
16. Not-null = "true" />
17.
18. <! - Lazy-loading is deactivated to demonstrate caching behavior ->
19. <set Name="languages" table="EMPLOYEE_SPEAKS_LANGUAGE" lazy="false">
20. <key Column="emp_id"/>
21. <many-to-many Column="lan_id"/>
22. </ Set>
23. </ Class>
24. </ Hibernate-mapping>
<hibernate-mapping package="com.wakaleo.articles.caching.businessobjects">
<class name="Employee" table="EMPLOYEE" dynamic-update="true">
<meta attribute="implement-equals"> true </ meta>
<id name="id" type="long" unsaved-value="null">
<column name="emp_id" not-null="true"/>
<generator/>
</ id>
<property column="emp_surname" name="surname" type="string"/>
<property column="emp_firstname" name="firstname" type="string"/>
<many-to-one name = "country"
column = "cn_id"
not-null = "true" />
<! - Lazy-loading is deactivated to demonstrate caching behavior ->
<set name="languages" table="EMPLOYEE_SPEAKS_LANGUAGE" lazy="false">
<key column="emp_id"/>
<many-to-many column="lan_id"/>
</ set>
</ class>
</ hibernate-mapping>
Assuming you use the employee object each time an employee will need to be said that language. Forced to hibernate automatically load associated languages collection, you set up a lazy property to false (). You also need a DAO to get all types of employee, the following code to help you achieve
Java code
1. Public class EmployeeDAO (
2.
3. Public List getEmployeesByCountry (Country country) (
4. Return SessionManager.currentSession ()
5.. CreateQuery (
6. "From Employee as e where e.country =: country"
7. + "Order by e.surname, e.firstname")
8.. SetParameter ( "country", country)
9.. List ();
10.)
11.)
public class EmployeeDAO (
public List getEmployeesByCountry (Country country) (
return SessionManager.currentSession ()
. createQuery (
"from Employee as e where e.country =: country"
+ "Order by e.surname, e.firstname")
. setParameter ( "country", country)
. list ();
)
)
Next, write some simple unit tests look at how the performance of it. As the previous examples, you need to know it was time to duplicate the performance of call
Java code
1. Public class EmployeeDAOTest extends TestCase (
2.
3. CountryDAO countryDao = new CountryDAO ();
4. EmployeeDAO employeeDao = new EmployeeDAO ();
5.
6. / **
7. * Ensure that the Hibernate session is available
8. * To avoid the Hibernate initialisation interfering with
9. * The benchmarks
10. * /
11. Protected void setUp () throws Exception (
12. Super.setUp ();
13. SessionManager.getSession ();
14.)
15.
16. Public void testGetNZEmployees () (
17. TestTimer timer = new TestTimer ( "testGetNZEmployees");
18. Transaction tx = SessionManager.getSession (). BeginTransaction ();
19. Country nz = countryDao.findCountryByCode ( "nz");
20. List kiwis = employeeDao.getEmployeesByCountry (nz);
21. Tx.commit ();
22. SessionManager.closeSession ();
23. Timer.done ();
24.)
25.
26. Public void testGetAUEmployees () (
27. TestTimer timer = new TestTimer ( "testGetAUEmployees");
28. Transaction tx = SessionManager.getSession (). BeginTransaction ();
29. Country au = countryDao.findCountryByCode ( "au");
30. List aussis = employeeDao.getEmployeesByCountry (au);
31. Tx.commit ();
32. SessionManager.closeSession ();
33. Timer.done ();
34.)
35.
36. Public void testRepeatedGetEmployees () (
37. TestGetNZEmployees ();
38. TestGetAUEmployees ();
39. TestGetNZEmployees ();
40. TestGetAUEmployees ();
41.)
42.)
public class EmployeeDAOTest extends TestCase (
CountryDAO countryDao = new CountryDAO ();
EmployeeDAO employeeDao = new EmployeeDAO ();
/ **
* Ensure that the Hibernate session is available
* To avoid the Hibernate initialisation interfering with
* The benchmarks
* /
protected void setUp () throws Exception (
super.setUp ();
SessionManager.getSession ();
)
public void testGetNZEmployees () (
TestTimer timer = new TestTimer ( "testGetNZEmployees");
Transaction tx = SessionManager.getSession (). BeginTransaction ();
Country nz = countryDao.findCountryByCode ( "nz");
List kiwis = employeeDao.getEmployeesByCountry (nz);
tx.commit ();
SessionManager.closeSession ();
timer.done ();
)
public void testGetAUEmployees () (
TestTimer timer = new TestTimer ( "testGetAUEmployees");
Transaction tx = SessionManager.getSession (). BeginTransaction ();
Country au = countryDao.findCountryByCode ( "au");
List aussis = employeeDao.getEmployeesByCountry (au);
tx.commit ();
SessionManager.closeSession ();
timer.done ();
)
public void testRepeatedGetEmployees () (
testGetNZEmployees ();
testGetAUEmployees ();
testGetNZEmployees ();
testGetAUEmployees ();
)
)
If you run the above code, you will get some data similar to the following
$ mvn test-Dtest = EmployeeDAOTest
...
testGetNZEmployees: 1227 ms.
testGetAUEmployees: 883 ms.
testGetNZEmployees: 907 ms.
testGetAUEmployees: 873 ms.
testGetNZEmployees: 987 ms.
testGetAUEmployees: 916 ms.
[surefire] Running com.wakaleo.articles.caching.dao.EmployeeDAOTest
[surefire] Tests run: 3, Failures: 0, Errors: 0, Time elapsed: 3684 sec
So for a country loading around 50 employees required to spend time around one second. This method is obviously too slow. This is typical of the N +1 query problem. If you enable SQL log, you will find on the employee table in a query, followed by hundreds of language table query, regardless of hibernate from the cache when an employee received the object, it will be all the associated heavy-duty language. How it can enhance its performance? The first thing to do is to enable employee to read and write cache, as follows
Java code
1. <hibernate-mapping Package="com.wakaleo.articles.caching.businessobjects">
2. <class Name="Employee" table="EMPLOYEE" dynamic-update="true">
3. <meta Attribute="implement-equals"> true </ meta>
4. <cache Usage="read-write"/>
5. ...
6. </ Class>
7. </ Hibernate-mapping>
<hibernate-mapping package="com.wakaleo.articles.caching.businessobjects">
<class name="Employee" table="EMPLOYEE" dynamic-update="true">
<meta attribute="implement-equals"> true </ meta>
<cache usage="read-write"/>
...
</ class>
</ hibernate-mapping>
You should also enable caching on the language category. Read-only cache is as follows
Java code
1. <hibernate-mapping Package="com.wakaleo.articles.caching.businessobjects">
2. <class Name="Language" table="SPOKEN_LANGUAGE" dynamic-update="true">
3. <meta Attribute="implement-equals"> true </ meta>
4. <cache Usage="read-only"/>
5. ...
6. </ Class>
7. </ Hibernate-mapping>
<hibernate-mapping package="com.wakaleo.articles.caching.businessobjects">
<class name="Language" table="SPOKEN_LANGUAGE" dynamic-update="true">
<meta attribute="implement-equals"> true </ meta>
<cache usage="read-only"/>
...
</ class>
</ hibernate-mapping>
And you need to configure the cache rules by adding the following content to the document ehcache.xml
Java code
1. <Cache name = "com.wakaleo.articles.caching.businessobjects.Employee"
2. MaxElementsInMemory = "5000"
3. Eternal = "false"
4. OverflowToDisk = "false"
5. TimeToIdleSeconds = "300"
6. TimeToLiveSeconds = "600"
7. />
8. <Cache name = "com.wakaleo.articles.caching.businessobjects.Language"
9. MaxElementsInMemory = "100"
10. Eternal = "true"
11. OverflowToDisk = "false"
12. />
<cache name = "com.wakaleo.articles.caching.businessobjects.Employee"
maxElementsInMemory = "5000"
eternal = "false"
overflowToDisk = "false"
timeToIdleSeconds = "300"
timeToLiveSeconds = "600"
/>
<cache name = "com.wakaleo.articles.caching.businessobjects.Language"
maxElementsInMemory = "100"
eternal = "true"
overflowToDisk = "false"
/>
But did not solve the N +1 query problem: When you load an employee when the object around 50 additional inquiries or perform. Here you will need at Employee.hbm.xml mapping document language associated cache is enabled, the following
Java code
1. <hibernate-mapping Package="com.wakaleo.articles.caching.businessobjects">
2. <class Name="Employee" table="EMPLOYEE" dynamic-update="true">
3. <meta Attribute="implement-equals"> true </ meta>
4.
5. <id Name="id" type="long" unsaved-value="null">
6. <column Name="emp_id" not-null="true"/>
7. <generator/>
8. </ Id>
9.
10. <property Column="emp_surname" name="surname" type="string"/>
11. <property Column="emp_firstname" name="firstname" type="string"/>
12.
13. <Many-to-one name = "country"
14. Column = "cn_id"
15.
16. Not-null = "true" />
17.
18. <! - Lazy-loading is deactivated to demonstrate caching behavior ->
19. <set Name="languages" table="EMPLOYEE_SPEAKS_LANGUAGE" lazy="false">
20. <cache Usage="read-write"/>
21. <key Column="emp_id"/>
22. <many-to-many Column="lan_id"/>
23. </ Set>
24. </ Class>
25. </ Hibernate-mapping>
<hibernate-mapping package="com.wakaleo.articles.caching.businessobjects">
<class name="Employee" table="EMPLOYEE" dynamic-update="true">
<meta attribute="implement-equals"> true </ meta>
<id name="id" type="long" unsaved-value="null">
<column name="emp_id" not-null="true"/>
<generator/>
</ id>
<property column="emp_surname" name="surname" type="string"/>
<property column="emp_firstname" name="firstname" type="string"/>
<many-to-one name = "country"
column = "cn_id"
not-null = "true" />
<! - Lazy-loading is deactivated to demonstrate caching behavior ->
<set name="languages" table="EMPLOYEE_SPEAKS_LANGUAGE" lazy="false">
<cache usage="read-write"/>
<key column="emp_id"/>
<many-to-many column="lan_id"/>
</ set>
</ class>
</ hibernate-mapping>
Through this configuration, you can get close to optimal performance
$ mvn test-Dtest = EmployeeDAOTest
...
testGetNZEmployees: 1477 ms.
testGetAUEmployees: 940 ms.
testGetNZEmployees: 65 ms.
testGetAUEmployees: 65 ms.
testGetNZEmployees: 76 ms.
testGetAUEmployees: 52 ms.
[surefire] Running com.wakaleo.articles.caching.dao.EmployeeDAOTest
[surefire] Tests run: 3, Failures: 0, Errors: 0, Time elapsed: 0228 sec
Query cache
In determining the circumstances, the correct cache a query result is very useful, not only to identify the object of just. For example, getCountries () method at the time each call may return a list of the same country. Therefore, apart from the cache outside the country category, and you should cache query results themselves.
In order to achieve this goal, you need to file hibernate.cfg.xml at hibernate.cache.use_query_cache property settings for the true, the following
<property name="hibernate.cache.use_query_cache"> true </ property>
Then required for any query cache at a time when the use of setCacheable () method, as follows
Java code
1. Public class CountryDAO (
2.
3. Public List getCountries () (
4. Return SessionManager.currentSession ()
5.. CreateQuery ( "from Country as c order by c.name")
6.. SetCacheable (true)
7.. List ();
8.)
9.)
public class CountryDAO (
public List getCountries () (
return SessionManager.currentSession ()
. createQuery ( "from Country as c order by c.name")
. setCacheable (true)
. list ();
)
)
However, it should not predict that the other procedures on the database any changes. So you should not use any of the secondary cache (or for the class and set the cache settings expired short time) if your data is always to ensure that the latest status.
The right to use hibernate cache
Cache is a powerful technology, hibernate provides a powerful, flexible, inconspicuous way to achieve it. Even if a lot of simple examples of the default settings for the actual performance can be raised. However, as much as a powerful tool, hibernate, or required some thinking and fine-tuning to get optimal results, and cache optimization, like other technologies, should be the use of a scalable, test-driven implementation approach. When the proper use of the time, a small amount of cache implementation that can improve the maximum degree of the program is running you.







