in Hibernate we are most commonly used in three categories of cache, the first level of cache, level two cache and query cache, the following we on the use of the three cache in the project and the pros and cons of analysis.
Caching is what it does to improve performance system performance, between the application system and the database and the data that exists in memory or on disk.
First, take a look at the primary cache, which is turned on and used by default.
First-level caching
The same kind of cache can often have several names, which is the result of a different perspective, from the life cycle perspective of the cache can also be called: Sessin cache, Thread-level cache, transaction-level cache. We programmed the thread, the transaction, the session of the three concepts are bound together into the threadlocal, while opening and closing the die is also called request-per-session-transaction programming;
When the session is closed, the objects in the cache are lost, which means that the cached data in the two different sessions is not the same, and the cached data cannot be accessed across sessions.
Data type of cached data
In the first level cache is the entity object, in the use of Query method get (), load (), iterate () Three method query will query the session cache first, if there is an object from the cache, if the cache does not go to the database inside the query.
Load () Test: Test note must be in the same transaction, when I am in the Spring Management session Test call two load () always query two times issued two SQL statements, also thought that session-level cache does not work, The original is because Hibernate integration spring after the transaction, the session is managed by spring, each call before and after the transaction level session automatically open and close, you can not control the middle process, Then the spring is removed to the hibernate original session, and then manually developed to close the transaction to ensure that in the same session, the same transaction inside the operation method, is actually sent a SQL statement, see the following code:
Load (), Get () method:
@Test public void TestLoad () { Session session=sf.opensession (); Session.begintransaction (); Category category1= (category) Session.load (category.class,1); Category category2= (category) Session.load (category.class,1); System.out.println (category1); System.out.println (Category2); Session.gettransaction (). commit (); Session.close (); }
Results
Hibernate:select category0_.id as id0_0_, category0_.name as name0_0_ from Category category0_ where category0_.id=? [Email protected] [Email protected]
The result is not only a statement is sent, but the two objects are printed in the same way.
Load (), get () The first query will issue a SQL statement from the database table inside the query, the second query will go to the cache in the first lookup, if no update modification operation, then the data will be read from the cache, otherwise query the database.
Save method
@Test public void Testget () { Session session=sf.opensession (); Session.begintransaction (); Category category1=new category (); Category1.setname ("News"); Session.save (category1); Category category2= (category) Session.load (Category.class,category1.getid ()); System.out.println (Category2.getname ()); Session.gettransaction (). commit (); Session.close (); }
Save also supports caching, when the Save method is executed first to add a data to the session cache, such as transaction commit or cache refresh to update the database, from the above execution process can be seen only issued an INSERT statement did not send a query statement, because the second time from the cache query.
Ps:save after executing get or load needs to know the ID of the object, when the Save method executes although there is no data in the database, but the object ID has been generated can be queried by this ID object.
BULK INSERT Data
When inserting data in bulk, take one piece of data at a time, such that inserting 20 data at a time does not require a single insertion.
public void Testinserbatch () {Session session = Sf.opensession (), session.begintransaction (); for (int i=0; i<1000; i++ {Category C = new category (); C.setname ("Test" + i); Session.save (c); if (i%20==0) {Session.flush ();}} Session.gettransaction (). commit (); Session.close ();}
Each time 20 data is cleaned up cache, each cleanup cache call Session.flush () method will emit 20 insert statements, but there is no data in the database and so all the data issued INSERT statement Unified COMMIT TRANSACTION, A transaction is a hierarchy with a session and therefore requires a unified control transaction.
Hibernate n+1 Problems
Hibernate often uses set and other sets to represent 1-to-many relationships, and in the Iron Academy project We do, we can retrieve the associated object or collection of objects according to the relationship when we get the entity, and we can set Cacade to update and delete the associated objects. This has to say that Hibernate's ORM is doing very well, very close to Oo's usage habits.
But the database access still must consider the performance problem, after setting 1 to many this kind of relationship, the query will appear the legendary n+1 question.
One-to-many: in a side, find the N objects, then need to be n objects associated with the collection, so that an original SQL query into a n+1 bar;
Many to one: in the multi-party, the query obtained M objects, then will also be M objects corresponding to the 1-side object out, also become m+1;
Ways to solve the problem:
1, using fetch crawl, Hibernate crawl strategy is divided into single-ended agent and collection agent crawl strategy.
Hibernate Crawl Strategy (single-ended agent crawl strategy):
Keeping the default is the following:
<many-to-one name= "Clazz" cascade= "save-update" fetch= "select"/>
Fetch= "Select" is to send another SELECT statement to fetch the current object associated entity or set fetch= "join"
<many-to-one name= "Clazz" cascade= "save-update" fetch= "join"/>
Hibernate will use an outer join with the SELECT statement to correlate the entity live collection at this time, lazy will expire
Hibernate Crawl Strategy (collection agent's fetch strategy):
Keeping the default (fetch= "select") is the following:
<set name= "Students" inverse= "true" >
<key column= "Clazz"/>
<one-to-many class= "Com.june.hibernate.Student"/>
</set>
1) fetch= "Select" will issue a separate statement query collection
2) Set fetch= "join" with a lazy invalidation of the outer join set
3) This fetch= "Subselect" also emits a SELECT statement that fetches the associated collection of all the entity objects that were previously queried. Fetch only affects HQL queries.
Opensessioninview problems
This problem arises due to load () lazy loading, the first query data using lazy load to query the ID of the data, when the use of data also need to go to the database query but at this time the database session has been closed, two ways to solve this problem is not to use lazy loading And the other is to develop the closed session at the Web layer, extending the session's life cycle.
Second-level cache
The second level cache is also called the process level cache or the Sessionfactory cache, can also be called the cluster-wide cache, needs the third party to implement, hibernate the default level two cache plug-in is Ehcache this cache, because the two level cache is the process level possibility to have the multithreading concurrency problem, You need to set the concurrency policy for the cache.
Hibernate level Two cache requires third-party plug-in support, hibernate default support for Ehcache for configuration please refer to: Spring AOP +ehcache Add cache for service layer method
Impact of a two-level cache on the method
Get ()/load ()
For these two methods have no effect, the first query from the database, the second first to determine if there is no data in the cache if you do not go to the database inside the query.
Query cache
The query cache is a cache of common attribute result sets, no entity objects are cached, and when the tables associated with the query cache are modified, the query cache life cycle ends and the data is emptied.
Configuration and use of the query cache:
The list method reads and writes the query cache, iterator does not use the query cache (query cache is only valid for query.list ())
The configuration of the query cache does not turn on the Hibernate3 configuration by default:
<property name= "Cache.provider_class" >org.hibernate.cache.NoCacheProvider</property> < Property Name= "Hibernate.cache.use_second_level_cache" >false</property> <property name= " Hibernate.cache.use_query_cache ">true</property>
In the code, add a sentence
Query.setcacheable (True)
The relationship between first level, level two, and query
The first level cache is always on, and we need to focus on the query cache and level two cache, and the query cache can be turned on only one or two.
when a level two cache is turned on, if the two session successively executes the load or get method, only one statement will be found from the cache for the second time, first from the primary cache, and if it is not found in the level two cache.
First -level cache interaction with level two cache
Prevents the first-level cache from interacting with level two caches, as set out below
Session.setcachemode (cachemode.ignore);
open a session to execute the query, it will first save the query results to a first-level cache, after the session is closed, the data in the primary cache is emptied, because the first-level cache is forbidden to interact with level two cache data, so the primary cache is closed after the structure is not saved to the level two cache. After the second session is opened, a query statement is sent, so there is no data in the level two cache.
Query cache vs. Level two cache
Turn on query, turn off level two
if two times execute query.list (), the first send query statement will save the ID of the result object to the query cache, the second will be removed from the query cache ID, based on the first level of cache lookup, and then level two cache, if not found will go to the database to find, The first-level cache is not related to the session, only the table.
Turn on the query and turn on level two caching
Two execution query.list (), the first time a query statement is sent, the result
Summarize:
Slow existence of a project is important to improve system performance, in addition to Ehcache, Memcache, Redis and other cache products are now very common, Redis has a rich data type and single-thread efficient access efficiency, Memcache is multi-threaded but efficient or not redis high.
These cache products can be distributed cache, Ehcache+rmi can be distributed cache synchronization, Memcache+redis support distributed, Redis also provides a high-availability solution: Master-slave replication several servers directly love you can switch.
Hibernate improves system performance with cache (level one, level two, query)