The accumulation and summarization of Hibernate cache application

Source: Internet
Author: User

Hibernate cache has been more difficult to master, the following analysis and summary of the reasons, I believe you will slowly understand that the original hibernate cache is also easy to grasp, but the premise requires that we must follow hands to verify, and then carefully experience, light look is no use

First, Hibernate cache (Session level cache)

Hibernate is a thread that corresponds to a session, and a thread can be viewed as a user. That is, the session cache (cache) can only be used by one thread, other threads are not used, and a primary cache is bound to threads. The hibernate cache life cycle is very short, and as with the session life cycle, the first level cache is also called session level cache or transaction level cache. If the TB transaction commits or rolls back, we say the session is closed and the life cycle is over.

  Lab 1: Experience Cache level: (Do it yourself)

The same session, issued two times the Load method query employee  emp= (employee) Session.load (employee. class, 1); System.out.println (Emp.getname ());//does not issue query statements, load uses cached EMP = (employee) session.load (employee. class, 1); System.out.println (Emp.getname ());

The second time the same data is queried for the first time, the second load method takes the data from the cache and does not issue SQL statements to the database for querying.

Caching is primarily used for queries, and many of Hibernate's methods are to first fetch data from the cache if it is not being fetched from the database to improve query efficiency such as Get ()/load (), iterate (), and persisted objects are stored in the cache. For example: Save the Entity object First, and then use the Load method to query the entity object that just saved, the Load method does not emit the SQL statement to the database query, but to the cache to fetch the data, because the Save method also supports caching.

二、一级 cache features and their applications:

  1.Session level cache, which is the same as Session bonding. it has the same life cycle as the session. The session is destroyed, and it is destroyed at the same time;

  2. Two sessions cannot share a primary cache, as it will accompany the creation and destruction of the session's life cycle;

  The 3.Session cache is an entity-level cache that is used only when querying the object level, and if you use HQL and SQL are query attribute levels, you do not use a first-level cache! Remember!!!

  4.iterate Query using the cache , will issue the query ID SQL and HQL statements, but will not issue a check entity, it will put the corresponding entity in the cache, some entity query if the cache is inside, it is queried from the cache, However, SQL and HQL statements with query IDs are issued. If the cache does not have it in the database query, and then put the query into the entity one by one into the cache, so there will be a n+1 problem arises.

  5.List () and iterate query differences: (Hands-on)

Using Iterate,list to query entity objects *n+1 problems, by default, using Query.iterate queries, there can be n+1 problems

The so-called N+1 is issued at the time of query n+1 SQL statement 1: First issue a Query object ID list sqln:

According to the ID list to the cache query, if there is no matching data in the cache, then the corresponding SQL statement according to the ID of the difference between list and iterate?

The list emits SQL statements each time, and the list puts data into the cache without taking advantage of the data in the cache

Iterate: Iterate takes advantage of cached data by default, but can be n+1 if no data exists in the cache

 6.Get () and load (), the Iterate method uses a first-level cache,

What is the difference between get and load? (Do It yourself)

1. For the Get method, hibernate confirms that the data exists for the ID, first in the session cache, then in the level two cache, without querying the database and returning NULL in the database.

2. The Load method loads the entity object, based on the configuration of the lazy attribute at the class level on the mapping file (true by default), which is discussed in some cases:

(1) If true, first look in the session cache to see if the ID corresponds to the existence of the object, does not exist then use lazy loading, return the entity's proxy class object (the proxy class is a subclass of the entity class, generated dynamically by Cglib). Wait until the specific use of the object (in addition to the OID) to query the level two cache and database, if you still do not find a qualifying record, will throw a objectnotfoundexception.

(2) If False, it is the same as the Get method lookup order, but eventually if no qualifying records are found, a objectnotfoundexception will be thrown.

Summary:

1, the Get method first query the session cache, no query two cache, and finally query the database; the Load method first queries the session cache, does not create the proxy, and only queries the two cache and database when the data is actually used.

2. If a record that matches the condition is not found, the Get method returns NULL, and the load method throws a objectnotfoundexception.

3. Load uses agents to delay loading data, and the Get method often returns objects with Entity data

Use:

1, if you want to do an object to increase the deletion and so on, the use of the Load method, performance improvement, you can use the proxy object, eliminating the opportunity to interact with the database, and when the actual use of the object's properties, only to interact with the database

2. If you want to load an object using its properties, use the Get method

  The 7.hiberate3 session stored procedure is as follows:

For example, Object objects Session.save (object);

This time will not put the data into the database, will be placed in the session cache, the database does not have a corresponding record, Session.flush (), only the SQL and HQL statements, the database has a corresponding record,

But the database is not available with Select, which is related to the database thing level.

Session.begintrransaction (). Commit ();

Things can be queried after they are submitted.

Session.flush () statement But why not write it, because commit () will call Flush () by default;

third, management level cache

Whenever you pass an object to the Save (), update (), or Saveorupdate () method, or use the load (), get (), list (), iterate (), or scroll () method to obtain an object, the The object will be added to the internal cache of the session. When the flush () method is subsequently called, the state of the object is synchronized with the database. If you do not want this synchronization to happen, or if you are working on a large number of objects and need to manage memory effectively, you can call the evict () method to remove these objects and their collections from the first-level cache.

Scrollableresult cats = Sess.createquery ("From Cat as Cat"). Scroll (), while (Cats.next ()) {    cat cat = (cat) Cats.get ( 0);    Dosomethingwithacat (cat);    Sess.evict (cat);}

The session also provides a contains () method to determine whether an instance is in the cache of the current session. If you want to clear all objects from the session cache, you need to call Session.clear ().

Iv. Hibernate level Two cache (Sessionfactory level cache)

The secondary cache needs to be sessionfactory to manage it, it is into the primary cache, everyone can use it, it is shared. Hibernate level Two caches support object caches, collection caches, query result set caches, and are optional for query result set caches.

Secondary caches are more complex and generally use third-party products. Hibernate provides a simple implementation, made with Hashtable, that can only be used as part of our testing, commercial or third-party products.

  Several excellent caching scenarios:

  1. Memcached Distributed Cache System 2, JBOSS cache 3, EhCache EhCache 2.1 provides JTA support for hibernate. 4. Infinispan Open source data grid platform

Using a cache is definitely a long-time, unchanged data that doesn't make much sense if the data that's constantly changing is put into the cache. It is not necessary to use caching because of the frequent changes or the need to query the database frequently. Hibernate has done some optimizations, and some third-party cache products have been integrated. The Ehcache cache product is used here.

Integration with Ehcache level two cache product: Ehcache jar file in Hibernate lib, we also need to set a series of cache usage policies, need a configuration file Ehcache.xml to configure.

  hibernate.cfg.xml Configuration (Hands-on)

<!--turn on level two cache--  <property name= "Hibernate.cache.use_second_level_cache" >true</property>  <!--open Query Cache--  <property name= "Hibernate.cache.use_query_cache" >true</property>  <!--prefix two cache domain names--  <!--<property name= "Hibernate.cache.region_prefix" >h3test</property>  -<!--cache provider third-  party products-  <property name= "Hibernate.cache.region.factory_class" >  net.sf.ehcache.hibernate.EhCacheRegionFactory  </property>  <!--Specify the cache profile location  -- <property name= "Hibernate.cache.provider_configuration_file_resource_path" >  ehcache.xml  </ Property>  <!--force Hibernate to store data in a more humane format in a two-level cache--  <property name= "Hibernate.cache.use_ Structured_entries >true</property>  <!--hibernate collects statistics that help with performance tuning-  <property name= "Hibernate.generate_statistics" >true</property>  

Ehcache configuration (Ehcache.xml) (Hands-on)

<?xml version= "1.0" encoding= "UTF-8"?>  <ehcache name= "H3test" >      <!--Specify the region name-->< Defaultcache  maxelementsinmemory= ""      <!--the maximum number of caches in memory-->eternal= "false"                          <!--cache is persistent-- Timetoidleseconds= ""     <!--when the cache entry is idle n seconds to destroy the-->timetoliveseconds= "" "    <!--when the cache entry is alive n seconds and then destroyed-- Overflowtodisk= "false" >    <!--hdd overflow--></defaultcache>  </ehcache>    

Entity read-only caching

Read-only caching reads only and does not require locks and transactions, since the cache does not change since the data is loaded from the database. If the data is read-only, such as referencing data, always use the "read-only" policy, because it is the simplest and most efficient strategy and a strategy for cluster security. Is the performance first strategy

Secondary cache test code (hands-on)

Session Session1 = Sf.opensession ();  Transaction T1 = session1.begintransaction ();  Ensure that the database has an identifier of 1 Voucher Voucher Voucher = (vocher) session1.get (Vocher.class, 1);  If the modification will error, the read-only cache does not allow modification of the   //voucher.setname ("AAA");  T1.commit ();  Session1.close (); Session Session2 = Sf.opensession ();  Transaction t2 = session2.begintransaction ();            Voucher = (vocher) session2.get (Vocher.class, 1);   Finds results in level two cache, does not produce SQL statements, does not manipulate database T2.commit ();  Session2.close ();  Sf.close ();   

The read-only cache does not allow updates and will error the can ' t write to a ReadOnly object. Allow new, (added directly to level two cache)

Read Write Cache Read write

Updates to the cache occur after the database transaction is complete. The cache requires a support lock. Updates the database in one transaction, updates the cache after the transaction completes successfully, and releases the lock. A lock is simply a specific way of invalidating a cache value, preventing other transactions from reading and writing the cache until it obtains a new database value. Those transactions would instead read the database directly

Entity read/ write Cache

Second-level cache test Code

Session Session1 = Sf.opensession ();  Transaction T1 = session1.begintransaction ();  Ensure that the database has an identifier of 1 Voucher Voucher Voucher = (vocher) session1.get (Vocher.class, 1);  If the modification will error, the read-only cache does not allow modification of the  voucher.setname ("AAA");  T1.commit ();  Session1.close ();        Session Session2 = Sf.opensession ();  Transaction t2 = session2.begintransaction ();  Voucher = (vocher) session2.get (Vocher.class, 1);   The entry has been modified by another transaction, at which time the database   T2.commit () is queried again;  Session2.close ();  Sf.close ();   

Allow updates to be automatically synced to the cache after updates. Allow new, automatically sync to cache when new records are added. Ensure that the Read Committed isolation level and the REPEATABLE Read isolation level (implemented through timestamp) lock the entire process, if the timestamp of the current transaction is earlier than the entry in the level two cache, indicating that the entry has been modified by another transaction, at which time the database is queried again, otherwise the cached data is used. Therefore guaranteed repeatable READ Isolation LEVEL

  Non-strict read-write cache nonstrict Read Write

Updates the database in one transaction, clears the cache before the transaction completes, and, for security purposes, clears the cache again after the transaction completes, regardless of the success of the transaction. Neither the need to support cache locks nor the need to support transactions. In the case of a cache cluster, a "clear cache" call invalidates all replicas, which is often referred to as a pull update policy. If your data reads a lot or has few concurrent cache accesses and updates, you can use the "nonstrict-read-write" policy. Thanks to its lightweight "pull" update strategy, it is usually the second best strategy for performance.

Entity non-strict read/write cache

Test the code slightly (I think you will verify it)

  Validation results

Allow updates, cache invalidation after update, need to be queried again. Allow new, new records to be added automatically to level two cache. The whole process is unlocked and not guaranteed.

  Transaction cache transactional (must be in the JTA environment)

Updates to the cache and database are wrapped in the same JTA transaction, so that the cache is always synchronized with the database. Both the database and the cache must support JTA. Unless you really want to put cache updates and database updates in a JTA transaction, don't use the "transactional" policy, because JTA requires lengthy two-phase commit processing, which makes it basically the worst-performing strategy.

Requires support for specific caches and JTA transaction support, not shown here.

Collection Cache

Demo read/write cache example, similar to previous entity cache tests, other self-test

Sessionfactory SF =   new Configuration (). Configure (). Buildsessionfactory ();  Session Session1 = Sf.opensession ();  Transaction T1 = session1.begintransaction ();   Ensure that the database has an identifier of 1 Usermodel  Usermodel user = (Usermodel) session1.get (Usermodel.class, 1);  User.getvouchers ();  T1.commit ();  Session1.close ();        Session Session2 = Sf.opensession ();  Transaction t2 = session2.begintransaction ();  user = (Usermodel) session2.get (Usermodel.class, 1);  User.getvouchers ();  T2.commit ();  Session2.close ();  Sf.close ();  

  Test conclusion:

Has the same meaning as the entity concurrency policy, but the collection cache caches only the identifier of the collection element, only the identifier of the corresponding entity in the level two cache, and then the identifier goes to the level two cache to find the corresponding entity and the final combination is returned for the collection.

Query caching (hands-on)

1. Ensure that the query cache is turned on in the global configuration.

2, modify the FarmModel.hbm.xml, add the following Red section configuration, representing the entity cache and read/write

3. Test code

Sessionfactory SF =   . New Configuration (). Configure (). Buildsessionfactory ();  Session Session1 = Sf.opensession ();  Transaction T1 = session1.begintransaction ();  Query query = session1.createquery ("Fromvoucher");  Even if the query cache is turned on globally, this is also a required  query.setcacheable (true);  list<voucher> voucherlist = Query.list ();  T1.commit ();  Session1.close ();  Session Session2 = Sf.opensession ();  Transaction t2 = session2.begintransaction ();  query = Session2.createquery ("from Voucher");  Even if the query cache is turned on globally, this is also a required  query.setcacheable (true);  Voucherlist = Query.list ();  T2.commit ();  Session2.close ();  Sf.close ();  

  Conclusion:

and the entity concurrency policy have the same meaning; Like the collection cache, only the identifier of the collection element is cached, only the identifier of the corresponding entity is stored in the level two cache, and then the identifier goes to the level two cache to find the corresponding entity and the final combination is returned for the collection.

when do I need to query the cache?

Most of the time, you cannot benefit from the result set cache. It is important to know how often the same query is executed repeatedly. Query caching can improve performance for applications that have very many queries but rarely insert, delete, or update very much. However, it is useless to write multiple queries, and it always fails.

Manage Level Two cache

For level two caching, there are many methods defined in Sessionfactory that clear the cache of instances, the entire class, the collection instance, or the entire collection.

Sessionfactory.evict (Cat.class, catId); Evict a particular catsessionfactory.evict (Cat.class);  Evict all catssessionfactory.evictcollection ("Cat.kittens", catId); Evict a particular collection of kittenssessionfactory.evictcollection ("Cat.kittens"); Evict all Kitten collectionssessionfactory.evictqueries ()//evict all queries// The Cachemode parameter is used to control how a specific session interacts with a level two cache. Cachemode.normal-Reads and writes data from the level two cache. Cachemode.get-Reads data from the level two cache and writes data to level two cache only when the data is updated. Cachemode.put-Writes data to a level two cache only, but does not read data from the level two cache. Cachemode.refresh-Writes data to a level two cache only, but does not read data from the level two cache. Force level two cache to read data from the database and flush cached content with hibernate.cache.use_minimal_puts settings

  Monitor level Two cache

If you need to view the contents of a level two cache or query cache area, you can use the statistics (Statistics) API. Get Hibernate statistics by Sessionfactory.getstatistics (). At this point, you must manually turn on the statistics option.

Hibernate.generate_statistics true Hibernate.cache.use_structured_entries True
v. Summary

Don't take it for granted that caching will certainly improve performance, only if you can harness it and the conditions are right. Hibernate's level Two cache limit is still relatively large, and the inconvenient use of JDBC may significantly reduce the performance of the update. If you do not understand the principle of the use of chaos, there may be 1+n problems. Improper use may also result in the reading of dirty data.

If you can't stand the many limitations of hibernate, do caching yourself at the application level.

The higher the level of caching, the better the effect will be. As if the disk has a cache, the database is to implement its own cache, although the database has a cache, our application is to do the cache. Because the underlying cache does not know what the high-level is going to do with the data, it can only be done in a more generic, high-level, targeted cache, so caching at higher levels will have a better effect.

The accumulation and summarization of Hibernate cache application

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.