Hibernate (d)

A secondary cache

1.1 concept

1.1.1 Cache

  • Cache: computer field in very general concept. It interposed between the application and the source persistent data store (e.g., file or database on the hard disk), which function is to reduce the frequency of application to read and write disk (persistent data store source), thereby improving the performance of applications running. Copy data in the cache data storage is the data source. Cache memory is usually physical media.

1.1.2 secondary cache

  • Hibernate provides cache mechanism: a cache, L2 cache.
  • Cache: Session-level cache, shared data in a single request.
  • Secondary cache: SessionFactory-level cache, the entire application sharing session factory, a shared L2 cache.

 

  • SessionFactory cache is divided into two parts:
  • Built-in caching: Use a Map, used to store configuration information, such as pre-defined HQL statement, provided to the Hibernate framework for their own use, foreign is read-only. It can not be written.
  • External Cache: using another Map, used to store user-defined data. The default is not open. External cache Hibernate provides only specifications (Interface), we need a third party to achieve.

1.1.3 secondary cache structure

 

1.1.4 Concurrent Access Policy

  •  transactional: transactional.
    • Applicable only managed cache.
    • Provide Repeateable Read transaction isolation level.
    • Applicable often read and rarely modified data.
    • Dirty reads and non-repeatable read concurrency problems can be prevented.
    • Cache support services, when an exception occurs, the cache can be rolled back.
  • read-write: read-write.
    • Provided Read Committed transaction isolation level.
    • Applicable in the context of non-cluster.
    • Use is often read and rarely modified data.
    • It prevents dirty reads.
    • Update the cache when it will lock the data cache.  
  • nonstrict-read-write: non-strict read-write.
    • Applicable rarely modified, occasionally allowing data to dirty read (two affairs simultaneously modify the data situation is rare).
    • It does not guarantee the consistency and cache data in the database.
    • Set a short expiration time for the cached data, so try to avoid dirty reads.
    • Data in the cache is not locked.  
  • read-only: Read only.
    • Applicable never modified data.
    • In this mode, if the data update operation, there will be abnormal.
    • Low transaction isolation level, high concurrency.
    • Also run perfectly in a clustered environment.  

1.1.5 application scenarios

  • Fit into two data cache:
    • Rarely modified.
    • Not very important data, allows concurrent problems occasionally occur.  
  • It does not fit into the data in the secondary cache:
    • Often modified.
    • Financial data, absolutely not allow concurrent problems arise,
    • And other application data sharing data.  

1.1.6 secondary cache provider

  • Hibernate only defines secondary cache interface, the need to select their own provider.
  • EHCache: as a process (single) cache within the range of physical storage media data can be memory or hard disk, as the Hibernate query cache provides support. Support clusters.
  • OpenSymphony: can be used as a cache within the scope of the process, the physical storage media data can be memory or hard disk, providing a wealth of data cache expiration policies, as the Hibernate query cache provides support.
  • SwarmCache: it can be used as a cache cluster-wide, but does not support Hibernate query cache.
  • JBossCache: it can be used as a cache cluster-wide, support Hibernate query cache.

1.2 Integration

1.2.1 ehcache of coordinates

<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.8.1</version>
</dependency>

1.2.2 Configuration hibernate.cfg.xml

<!--配置二级缓存-->
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.internal.SingletonEhcacheRegionFactory</property>
  • Complete hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!--配置数据库连接参数-->
        <property name="connection.url">
            <![CDATA[
                jdbc:mysql://localhost:3306/hibernate?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
            ]]>
        </property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>
        <!--是否显示SQL-->
        <property name="show_sql">true</property>
        <!--是否格式化SQL-->
        <property name="format_sql">true</property>
        <!--是否自动提交事务-->
        <property name="connection.autocommit">true</property>

        <property name="hbm2ddl.auto">update</property>

        <property name="hibernate.id.new_generator_mappings">
        <-! Configuration c3p0 -></ Property>to false

        <property name="hibernate.connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider
        </property>
        <property name="hibernate.c3p0.max_size">2</property>
        <property name="hibernate.c3p0.min_size">2</property>
        <property name="hibernate.c3p0.timeout">5000</property>
        <property name="hibernate.c3p0.max_statements">100</property>
        <property name="hibernate.c3p0.acquire_increment">2</property>

        <!--配置二级缓存-->
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.internal.SingletonEhcacheRegionFactory</property>


        <! - set the isolation level -> 
        <Property name = "the hibernate.connection.isolation">. 4 </ Property> 

        <! - The mapping in the table and JavaBean -> 
        <Mapping class = "com.sunxiaping. domain.Customer "/> 
        <Mapping class =" com.sunxiaping.domain.Order "/> 


    </ the session-Factory> 
</ Hibernate-Configuration>
View Code

1.2.3 Class and aggregate buffer configuration

  • Customer.java
package com.sunxiaping.domain;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import javax.persistence.*;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;


/**
 * 客户
 */
@Setter
@Getter
@NoArgsConstructor
@Entity
@Table(name = "`customer`")
@Cacheable
@Cache(usage =CacheConcurrencyStrategy.READ_ONLY)
 public  class the Customer the implements the Serializable {
     / ** 
     * Primary 
     * / 
    @Id 
    @GeneratedValue (Strategy = GenerationType.AUTO)
     Private Integer ID;
     / ** 
     * customer names 
     * / 
    Private String name; 

    / ** 
     * a there are many customer orders 
     * party waiving the right to maintain a foreign key 
     * / 
    @OneToMany (the mappedBy = "the customer", Cascade CascadeType.ALL = {}, FETCH = FetchType.LAZY) 
    @Cache (Usage = CacheConcurrencyStrategy.READ_ONLY)
     Private Set<Order> orders = new HashSet<>();


}
  • Order.java
package com.sunxiaping.domain;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import javax.persistence.*;
import java.io.Serializable;
import java.math.BigDecimal;

/**
 * 订单
 */
@Setter
@Getter
@NoArgsConstructor
@Entity
@Table(name = "`order`")
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public classThe Order the implements the Serializable {
     / ** 
     * Primary 
     * / 
    @Id 
    @GeneratedValue (Strategy = GenerationType.AUTO)
     Private Integer ID;
     / ** 
     * Order name 
     * / 
    Private String name;
     / ** 
     * Price 
     * / 
    Private the BigDecimal. Price; 

    / ** 
     * a part of a customer order, multi maintaining foreign key 
     * / 
    the @ManyToOne (Cascade = CascadeType.ALL in {}, FETCH = FetchType.EAGER) 
    @JoinColumn (name = "CID" ) 
    @ org.hibernate.annotations.Cache ( Usage = CacheConcurrencyStrategy.READ_WRITE)
    private Customer customer;

}

1.2.4 ehcache.xml

<? Xml Version = "1.0" encoding = "UTF-8" ?> 
< Ehcache xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" 
         xsi: noNamespaceSchemaLocation = "HTTP: // Ehcache .org / ehcache.xsd " 
         UpdateCheck =" to false " > 

    <-! set drive directory -> 
    < diskStore path =" D: \\ TEMP " /> 
    <-! maxElementsInMemory cache maximum number -> 
    <! - Eternal whether permanent, if the value is set to true, the timeout failure -> 
    <! - the time elapsed before timeToIdleSeconds failure -> 
    <!- survival timeToLiveSeconds time before failure -> 
    <! -The default buffer size diskSpoolBufferSizeMB 30M -> 
    <-! maxElementsOnDisk the maximum number of disk cache -> 
    - <! written to the hard disk cache overflowToDisk exceeds the maximum number -> 
    < defaultCache
             maxElementsInMemory = "10000" 
            Eternal = " to false " 
            timeToIdleSeconds =" 120 " 
            timeToLiveSeconds =" 120 " 
            overflowToDisk =" to true " 
    /> 
</ Ehcache >
View Code

1.3 Test

1.3.1 prove the existence of the secondary cache

  • Example:
package com.sunxiaping.test;

import com.sunxiaping.domain.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class HibernateTest {

    @Test
    public void test() {

        Configuration configuration = new Configuration().configure();

        SessionFactory sessionFactory = configuration.buildSessionFactory();

        Session session =sessionFactory.openSession (); 

        the Transaction Transaction = session.beginTransaction (); 

        // After the query is executed on the cache and secondary cache, 
        the Customer Session.get C1 = (the Customer. class ,. 1 ); 
        System.out.println (C1); 

        Session.clear (); 

        // if there is data in the secondary cache, the secondary cache fetch data from 
        the Customer Session.get C2 = (the Customer. class ,. 1 ); 
        System.out.println (C2) ; 

        transaction.commit (); 

        Session.close (); 
        sessionFactory.close (); 
    } 

}

 

  • Summary: Class-level cache, but cache data, and cache buffer is the object itself.

1.3.2 proof of collection-level cache

  •  Example:
package com.sunxiaping.test;

import com.sunxiaping.domain.Customer;
import com.sunxiaping.domain.Order;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

import java.util.Set;

public class HibernateTest {

    @Test
    public void test() {

        Configuration configuration = new Configuration().configure();

        SessionFactory sessionFactory =configuration.buildSessionFactory (); 

        the Session the session = sessionFactory.openSession (); 

        the Transaction Transaction = session.beginTransaction (); 

        // After the query is executed on the cache and secondary cache, 
        the Customer Session.get C1 = (the Customer. class ,. 1 ); 
        System.out.println (C1); 
        the Set <the Order> Orders = c1.getOrders (); 
        System.out.println (Orders); 

        Session.clear (); 

        // if there is data in the secondary cache, secondary cache fetch data from 
        the Customer Session.get C2 = (the Customer. class ,. 1 ); 
        System.out.println (C2); 
        //The default cache secondary cache which is the Order id, and then find the class-level cache according to ID 
        the Set <Order> = the Orders1 c2.getOrders (); 
        System.out.println (the Orders1); 

        transaction.commit (); 

        the session. Close (); 
        sessionFactory.close (); 
    } 

}

 

 

  • Summary: OID value of the aggregate buffer cache only the associated object, if necessary, to find the cache from the class, if the class is not cached, from the database lookup.

1.3.3 Query Cache

  • By default query cache is not used, you need to manually open.
  • The query cache: HQL statement will be binding and the query results. HQL statement by the same content can be cached.
  • By default Query query results only on the cache and secondary cache, but do not get from the primary and secondary cache.
  • Query Cache Query lets get from the secondary cache.

 

  • Example:
package com.sunxiaping.test;

import com.sunxiaping.domain.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;
import org.junit.Test;

import java.util.List;

public class HibernateTest {

    @Test
    public void test() {
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();

        Query query = session.createQuery(" FROM Customer ");
        query.setCacheable(true);//设置允许缓存
        List<Customer> list = query.list();
        for (Customer customer : list) {
            System.out.println(customer);
        }

        Customer customer1 = session.get(Customer.class, 1);
        System.out.println(customer1);

        transaction.commit();
        session.close();

        sessionFactory.close();
    }

}

 

1.3.4 timestamp cache

  •  Any operations are recorded in the time stamp of the operation.

 

  • Example:
package com.sunxiaping.test;

import com.sunxiaping.domain.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;
import org.junit.Test;

public class HibernateTest {

    @Test
    public void test() {
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session1 = sessionFactory.openSession();
        Transaction transaction = session1.beginTransaction();

        /**
         * 先修改用户信息
         */
        Query query = session1.createQuery(" update Customer set name =:name where id =:id");
        query.setParameter("name", "李四");
        query.setParameter("id", 1);
        query.executeUpdate();

        transaction.commit();
        session1.close();

        Session session2 = sessionFactory.openSession();
        Transaction transaction2 = session2.beginTransaction();

        Customer customer = session2.get(Customer.class, 1);
        System.out.println(customer);

        transaction2.commit();
        session2.close();
        sessionFactory.close();
    }

}

 

Guess you like

Origin www.cnblogs.com/xuweiweiwoaini/p/11562579.html