The object state

Object state in Hibernate:

  • Temporary/transient state
  • Persistent state
  • The free state

Learning about Hibernate object state is to get a clearer idea of Hibernate’s design philosophy and is the basis of level 1 caching… A little knowledge, of course

Temporary/transient state

When we directly new out the object is temporary/instantaneous state..

  • The object has not been persisted.
  • It is not managed by the Session

Persistent state

When an object is stored in a database, it is in a persistent state

  • When the session is called the save/saveOrUpdate/get/load/list method, the object’s persistent state
  • There is corresponding data in the database
  • Managed by Session
  • When changes are made to object properties, they are reflected in the database!

Let’s test this: when changes are made to object properties, they are reflected in the database!


        session.save(idCard);
        idCard.setIdCardName("I'm a test persistent object.");

Copy the code

The free state

When the Session is closed, the persistent object becomes free…

  • Not in session management
  • There are corresponding records in the database


Level 1 cache

Hibernate has a level 1 cache and a level 2 cache. This section focuses on level 1 cache

What is level 1 caching?

Hibenate level 1 caching, also known as session caching, can reduce the number of database accesses within the scope of a session! Session scope only! Session closed, level 1 cache invalid!

Anything in the persistent object state is session-managed, that is, in the Session cache!

The Session cache is maintained by Hibernate, and users cannot manipulate the cached content. If you want to manipulate cached content, you must use the Evit/Clear method provided by Hibernate.

Why cache?

Reduce the number of database accesses! Thus improving hibernate execution efficiency!

test

Let’s take a look at how Hibernate reduces the number of database accesses.

My User table now has this entry:

		// Put data into cache
        User user = (User) session.get(User.class, 1);

		// The field to be modified is found to be the same as cache
        user.setUserName("Hello 2");
Copy the code

Same thing with the data


        User user = null;
        user = (User) session.get(User.class, 1);
        user = (User) session.get(User.class, 1);

Copy the code


Cache-specific methods

There are three common methods associated with caching:

  • session.flush(); Synchronize level 1 cache with the database

  • session.evict(arg0); Clears the specified object in level 1 cache

  • session.clear(); Clears all objects cached in level 1 cache

  • clear


        User user = null;
        user = (User) session.get(User.class, 1);

        // Clear the cache, so that the next fetch can not be fetched from the cache
        session.clear();
        user = (User) session.get(User.class, 1);

Copy the code
  • flush

In the case of caching, modify the data of the same record, whichever is last… So there is only one UPDATE


        User user = null;
        user = (User) session.get(User.class, 1);

        user.setUserName("I'm number one.");
        user = (User) session.get(User.class, 1);
        user.setUserName("I'm number two.");

Copy the code

If I force it to synchronize with the database, there are two updates

        User user = null;
        user = (User) session.get(User.class, 1);

        user.setUserName("I'm number one.");
 		session.flush();
        user = (User) session.get(User.class, 1);
        user.setUserName("I'm number two.");

Copy the code

Normally, we use it in batch processing, because the cache is also sized, and if 1000 data inserts are cached, Hibernate may crash…

  • Flush () with the database at certain intervals
  • Clear ()

Note that different sessions do not share the cache!

The Iterator and list

We can use list() to get all the data, or we can use iterator() to get an iterator, iterate over the iterator… So what’s the difference?

. When I saw the video, I said:

But in my tests: lists can also fetch cached data

Of course, Iterator can also fetch cached data

Therefore, it is still convenient to use list() when retrieving data!

Lazy loading

Lazy loading is when the data is used to fetch the data, execute the corresponding SQL statement… Do not load data when it is not used yet!

The main purpose is to improve Hibernate performance and execution efficiency!

  • Get: load in time, as long as the get method to query the database immediately
  • Load: Lazy load is used by default. When data is needed, the database is queried.

Lazy loading experience again

        User user = (User) session.load(User.class, 1);

        System.out.println("...");
        System.out.println(user);

Copy the code

We can use the usual lazy attribute in the corresponding configuration file

Turn lazy loading off:

    <class name="IdCard" table="IdCard" lazy="false">
Copy the code

Lazy has three attributes:

  • True uses lazy loading
  • False Disables lazy loading
  • Extra (improve efficiency in lazy collection loading) [only for set tags, list, etc.]
    • The SQL of the query is sent to the database only when the data is actually used;
    • If you call the size()/isEmpty() method of the collection, it’s just statistics and doesn’t really query the data!

Lazy loading exception

Lazy loading cannot be used when the Session is closed, otherwise an exception will be reported


Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session
Copy the code

With this exception, we have four ways to resolve it:

  • Method 1: Use data first
    • dept.getDeptName();
  • Method 2: Force the proxy object to be initialized
    • Hibernate.initialize(dept);
  • Method 3: Turn off lazy loading
    • Set the lazy = false;
  • ** Mode 4: Close session after using data! 支那

Hibernate Level 2 Cache

We’ve already covered level 1 caching, which is the Session cache, and it only works within the scope of a Session… The duration is within the scope of the Session and is relatively small

Hibernate provides second-level caching: Second-level caching is application-based caching that can be used by all sessions

  • Hibernate provides second-level caching with a default implementation and is a pluggable caching framework! If the user wants to use the second-level cache, it can be configured in hibernate.cfg.xml. Do not want to use, directly remove, does not affect the code.
  • If the framework provided by Hibernate does not work, users can switch to another caching framework or implement their own caching framework.

Hibernate level 2 cache: Stores commonly used classes


Configuring Level 2 Cache

Since the second-level cache comes with Hibernate, we can find the corresponding information in hibernate.properties file..

  • #hibernate.cache. Use_second_level_cache false
  • #hibernate.cache.use_query_cache true
  • Choose a cache implementation

  • #hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider
  • #hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider
  • Hibernate. Cache. Provider_class org. Hibernate. Cache. HashtableCacheProvider default implementation
  • #hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider
  • #hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider
  • #hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider

From the configuration file, we can find that level 2 cache is not enabled by default, so we need to manually enable it as follows:

  • 1) Enable level 2 cache
  • 2) Specify the cache framework
  • 3) Specify which classes are added to the level 2 cache

Enabling Level 2 Cache

Enable level 2 caching in the hibernate.cfg. XML file


		<! -- a. Enable level 2 cache -->
		<property name="hibernate.cache.use_second_level_cache">true</property>
Copy the code

Specifying the cache framework

Specify Hibernate’s own second-level caching framework


		<! -- b. Specify which cache framework to use (provided by default) -->
		<property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
Copy the code

Specifies which classes are added to the level 2 cache


	    <! -- c. Specify which classes to add to the secondary cache -->
        <class-cache usage="read-write" class="zhongfucheng.aa.Monkey"/>
        <class-cache usage="read-only" class="zhongfucheng.aa.Cat"/>
Copy the code

Testing:

We know that level 1 cache is the cache of sessions, so we should use two sessions when testing level 2 cache. If the second Session gets cached data, then second-level caching is useful.


package zhongfucheng.aa;

import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;

public class App5 {
    public static void main(String[] args) {


        // Get the load configuration management class
        Configuration configuration = new Configuration();
        // Load the mapping file corresponding to the class!
        configuration.configure().addClass(Animal.class);
        // Create a Session factory object
        SessionFactory factory = configuration.buildSessionFactory();
        // Get the Session object
        Session session1 = factory.openSession();
        // If you use Hibernate to operate a database, you need to start a transaction and get the transaction object
        Transaction transaction = session1.getTransaction();
        // Start the transaction
        transaction.begin();
        Monkey monkey = (Monkey) session1.get(Monkey.class,"40283f815be67f42015be67f43240001" );
        System.out.println(monkey.getName());
        System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");



        Session session2 = factory.openSession();
        Transaction transaction2 = session2.getTransaction();
        transaction2.begin();
        Monkey monkey2 = (Monkey) session1.get(Monkey.class, "40283f815be67f42015be67f43240001");
        System.out.println(monkey2.getName());


        // Commit the transaction
        transaction.commit();
        transaction2.commit();

        / / close the Sessionsession1.close(); session2.close(); }}Copy the code

You get cached data!


Caching strategies

When we put Animal in the second level cache, it was read only

In other words, it can only be read, but not written. Let’s see how writing works:


  monkey2.setName("Little Monkey");
Copy the code

An exception was thrown….


There are four attributes for usage:

  • ** Objects placed in level 2 cache, read-only; 支那
  • Non-strict reading and writing
  • Reading and writing; Objects placed in level 2 cache can be read and written.
  • (Transaction-based strategy)

Set the cache

If the data we query in the database is a collection… Hibernate does not set level 2 caching for collection data by default… So you still need to read and write information from the database

Next, let’s see what it does to set the collection to level 2 cache:

  • Configure the collection in the object as a level 2 cache in hibernate.cgf.xml
		<! Set cache --> set cache
		<collection-cache usage="read-write" collection="cn.itcast.b_second_cache.Dept.emps"/>
Copy the code
  • Test code:

	public void testCache(a) {
		Session session1 = sf.openSession();
		session1.beginTransaction();
		// a. Query once
		Dept dept = (Dept) session1.get(Dept.class, 10);
		dept.getEmps().size();/ / collection
		session1.getTransaction().commit();
		session1.close();
		
		System.out.println("-- -- -- -- -- -");
		
		// Second session
		Session session2 = sf.openSession();
		session2.beginTransaction();
		// a. Query once
		dept = (Dept) session2.get(Dept.class, 10);  // Level 2 cache is configured; The database is not queried here
		dept.getEmps().size();
		
		session2.getTransaction().commit();
		session2.close();
	}
Copy the code

The query cache

List () and iterator() will put the data in level 1 cache, but level 1 cache is only valid in Session scope… If you want to use it across sessions, you need to set up the query cache

We also see a query cache configuration in the configuration file..

#hibernate.cache.use_query_cache trueCopy the code

In other words, the default query data is not placed in the secondary cache. If we want to put the query data into the secondary cache, we need to enable it in the configuration file

		<! -- Enable query cache -->
		<property name="hibernate.cache.use_query_cache">true</property>
Copy the code
  • When using program queries, setCacheable() is also called and set to query cache.

	@Test
	public void listCache(a) {
		Session session1 = sf.openSession();
		session1.beginTransaction();
		SetCacheable specifies whether to query from level 2 cache or to place it in level 2 cache.
		Query q = session1.createQuery("from Dept").setCacheable(true);
		System.out.println(q.list());
		session1.getTransaction().commit();
		session1.close();
		
		
		Session session2 = sf.openSession();
		session2.beginTransaction();
		q = session2.createQuery("from Dept").setCacheable(true);
		System.out.println(q.list());  // Do not query the database: query cache needs to be enabled
		session2.getTransaction().commit();
		session2.close();
	}
Copy the code

If the article has the wrong place welcome to correct, everybody exchanges with each other. Students who are used to reading technical articles on wechat and want to get more Java resources can follow the wechat public account :Java3y