[] MyBatis MyBatis acerca de la memoria caché y caché secundaria, usted debe ser consciente de estas

directorio

1, caché L1

1.1 Somos una sqlSession, la tabla de usuarios para dos consultas, ver la instrucción SQL que emitieron Según ID.

1.2 En el mismo cuadro es una consulta de un usuario dos veces, pero llevó a cabo dos veces una operación de actualización entre la consulta.

proceso de consulta 1.3 caché

1.4 mybatis y primavera integración da como resultado un error de caché

1.5 resumen

2, la memoria caché secundaria

2.1 el caché secundario utilizando

2.1.1 crear un Bean POJO y la serialización

2.1.2 archivo de asignación de caché de segundo nivel abierto

2.1.3 caché secundaria abierta en el SqlMapConfig.xml

2.1.4 Pruebas

Cuando se utiliza el muelle de caché secundaria integrada 2.1.5 mybatis

2.2 defectos cache secundaria


Proporcionar mybatis caché y caché secundario para nosotros, se puede entender por la figura siguiente:

  • caché de nivel es el nivel SqlSession caché. En la operación de base de datos sqlSession requiere objeto de configuración en el objeto tiene una estructura de datos (el HashMap) para almacenar datos de la caché. área de datos de la caché (la HashMap) entre mutuamente diferentes sqlSession no se ve afectada.
  • cache secundaria es mapper nivel SqlSession caché, un SqlSession pluralidad de operar declaración el mismo Mapper sql, una pluralidad de cache secundaria puede ser compartida, caché secundaria a través de la SqlSession. La caché secundaria es subyacente HashMap. (Con un Mapper es esencialmente el mismo espacio de nombres)

 

1 , caché L1

Somos una sqlSession, la tabla de usuarios para dos consultas, ver la instrucción SQL que emitieron Según ID.

 

1.1 Somos una sqlSession en, por usuario basada mesa de Identificación llevó a cabo dos investigaciones, consideramos que su problema sql declaración del caso.

@Test
public void testSelectOrderAndUserByOrderId(){
    //根据 sqlSessionFactory 产生 sqlsession
    SqlSession sqlSession = sessionFactory.openSession();
    String statement = "one.to.one.mapper.OrdersMapper.selectOrderAndUserByOrderID";
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    //第一次查询,发出sql语句,并将查询的结果放入缓存中
    User u1 = userMapper.selectUserByUserId(1);
    System.out.println(u1);

    //第二次查询,由于是同一个sqlSession,会在缓存中查找查询结果
    //如果有,则直接从缓存中取出来,不和数据库进行交互
    User u2 = userMapper.selectUserByUserId(1);
    System.out.println(u2);

    sqlSession.close();
}

Imprimir la información sobre la consola Comprobar:

 

1.2 La misma es usuario consulta de tabla dos veces, pero el doble tenía una entre la consulta de actualización de operaciones.

@Test
public void testSelectOrderAndUserByOrderId(){
    //根据 sqlSessionFactory 产生 sqlsession
    SqlSession sqlSession = sessionFactory.openSession();
    String statement = "one.to.one.mapper.OrdersMapper.selectOrderAndUserByOrderID";
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    //第一次查询,发出sql语句,并将查询的结果放入缓存中
    User u1 = userMapper.selectUserByUserId(1);
    System.out.println(u1);

    //第二步进行了一次更新操作,sqlSession.commit()
    u1.setSex("女");
    userMapper.updateUserByUserId(u1);
    sqlSession.commit();

    //第二次查询,由于是同一个sqlSession.commit(),会清空缓存信息
    //则此次查询也会发出 sql 语句
    User u2 = userMapper.selectUserByUserId(1);
    System.out.println(u2);

    sqlSession.close();
}

 Imprimir situación de la consola:

 

1.3 proceso de consulta caché

1, la primera vez que el usuario envía una consulta a la información de identificación del usuario 1, el primero en encontrar el caché si hay información para la identificación del usuario 1, si no, la información del usuario desde una consulta de base de datos. Para dar a la información del usuario, la información de usuario almacenada en la caché.

2, si el sqlSession intermedia para realizar operaciones de confirmación (insertar, actualizar, eliminar), SqlSession se vacía la memoria caché, con el propósito de hacerlo a fin de permitir almacenar en la memoria caché es la información más reciente, sucio evitar lee.

3, la segunda investigación iniciada por la información de identificación del usuario para el usuario 1, el primero en encontrar el caché si hay información para la identificación del usuario 1, la caché de allí, los usuarios obtener información directamente de la memoria caché.

 

1.4 mybatis y primavera integración da como resultado un error de caché

Utilizamos la primavera de integrar los MyBatis, encontrará nuestra invalidación de caché de nivel, es decir, si el código 1.1 se ejecuta en el proyecto de la primavera, a continuación, las dos consultas se ejecutarán instrucción SQL.

Esto se debe a que después de la integración de la primavera mybatis, sqlSession para ir a la gestión de contenedores de primavera, después de cada ejecución de SQL, primavera sqlSession cerrado, por lo que la caché y luego fallar.

 

1.5 resumen

Caché : la base de datos en la misma sesión (sqlSession) preguntó en la información se colocará en la memoria caché local , si querían obtener los mismos datos directamente desde la memoria caché , no otra vez a los datos de consulta de base de datos

Un SqlSession tiene un caché , la memoria caché es una memoria caché local.

 

mybatis siempre en la memoria caché , diferente SqlSession caché, los datos no puede ser compartida

 

Hay caso de fallo de caché, después de un fallo de caché, la segunda vez también se enviará la misma consulta a la base de datos SQL.

A los casos de invalidación de caché:

  1. diferentes sqlSession
  2. Cuando el objeto es el mismo tiempo sqlSession, diferentes términos de consulta, ya que el primer caché de consulta cuando no hay una segunda consulta de datos necesarios
  3. SqlSession cuando el mismo objeto, la operación de inserción entre dos sondeos
  4. Cuando el mismo objeto es sqlSession, borrar manualmente los datos en la memoria caché

 

¿Cuánto tiempo de ciclo de vida de caché?

  1. MyBatis al abrir una sesión de base de datos crea un nuevo SqlSession objetos, SqlSession objeto tendrá un nuevo Ejecutor objeto. Ejecutor objeto de celebrar una nueva PerpetualCache objetos; al terminar la sesión, SqlSession objeto y su interior ejecutor objeto también PerpetualCache objetos juntos también dio a conocer.
  2. Si SqlSession llamar al cerrar () método, se puede soltar una caché PerpetualCache objetos, la PerpetualCache objeto se invalida, de manera que una caché no estará disponible.
  3. Si SqlSession llama clearCache () , se borrará PerpetualCache objeto de datos, pero el objeto todavía puede ser utilizado.
  4. SqlSession realizar cualquiera de actualización de la operación ( update () , eliminación () , insert () ) , se borrará PerpetualCache objeto de datos, pero el objeto puede seguir utilizando

 

2 , la memoria caché secundaria

cache secundaria y principio cache como un principio, la primera consulta, los datos se colocan en la caché, entonces la segunda consulta se toma directamente a la caché. Sin embargo, una caché se basa sqlSession, y se basa en espacio de nombres de archivo de caché secundaria Mapper, que se puede compartir la memoria caché L2 pluralidad sqlSession mapeador en una región, y si tanto el asignador mismo espacio de nombres, incluso si los dos un mapeador, consulta entonces SQL para realizar tanto asignador de datos también estará presente en la misma zona en la cache secundaria.

 

espacio de nombres por defecto es Mapper nombre completo de la clase. Así mismo Mapper también asegura que el mismo espacio de nombres

 

 

2.1 el caché secundario utilizando

2.1.1 crear un grano de POJO y la serialización

Dado que los datos de caché secundario no está necesariamente almacena en la memoria, su medio de almacenamiento variarse, por lo que las necesidades de caché de objeto para realizar la serialización. (Si se almacena en la memoria, no se encontró la secuencia de la lata.)

public class Student implements Serializable{
    private static final long serialVersionUID = 735655488285535299L;
    private String id;
    private String name;
    private int age;
    private Gender gender;
    private List<Teacher> teachers;
    setters&getters()....;
    toString();        
}

 

2.1.2 archivo de asignación de caché de segundo nivel abierto

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yihaomen.mybatis.dao.StudentMapper">
    <!--开启本mapper的namespace下的二级缓存-->
    <!--
        eviction:代表的是缓存回收策略,目前MyBatis提供以下策略。
        (1) LRU,最近最少使用的,一处最长时间不用的对象
        (2) FIFO,先进先出,按对象进入缓存的顺序来移除他们
        (3) SOFT,软引用,移除基于垃圾回收器状态和软引用规则的对象
        (4) WEAK,弱引用,更积极的移除基于垃圾收集器状态和弱引用规则的对象。这里采用的是LRU,
                移除最长时间不用的对形象
        flushInterval:刷新间隔时间,单位为毫秒,这里配置的是100秒刷新,如果你不配置它,那么当
        SQL被执行的时候才会去刷新缓存。
        size:引用数目,一个正整数,代表缓存最多可以存储多少个对象,不宜设置过大。设置过大会导致内存溢出。
        这里配置的是1024个对象
        readOnly:只读,意味着缓存数据只能读取而不能修改,这样设置的好处是我们可以快速读取缓存,缺点是我们没有
        办法修改缓存,他的默认值是false,不允许我们修改
    -->
    <cache eviction="LRU" flushInterval="100000" readOnly="true" size="1024"/>
    <resultMap id="studentMap" type="Student">
        <id property="id" column="id" />
        <result property="name" column="name" />
        <result property="age" column="age" />
        <result property="gender" column="gender" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler" />
    </resultMap>
    <resultMap id="collectionMap" type="Student" extends="studentMap">
        <collection property="teachers" ofType="Teacher">
            <id property="id" column="teach_id" />
            <result property="name" column="tname"/>
            <result property="gender" column="tgender" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
            <result property="subject" column="tsubject" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
            <result property="degree" column="tdegree" javaType="string" jdbcType="VARCHAR"/>
        </collection>
    </resultMap>
    <select id="selectStudents" resultMap="collectionMap">
        SELECT
            s.id, s.name, s.gender, t.id teach_id, t.name tname, t.gender tgender, t.subject tsubject, t.degree tdegree
        FROM
            student s
        LEFT JOIN
            stu_teach_rel str
        ON
            s.id = str.stu_id
        LEFT JOIN
            teacher t
        ON
            t.id = str.teach_id
    </select>
    <!--可以通过设置useCache来规定这个sql是否开启缓存,ture是开启,false是关闭-->
    <select id="selectAllStudents" resultMap="studentMap" useCache="true">
        SELECT id, name, age FROM student
    </select>
    <!--刷新二级缓存
    <select id="selectAllStudents" resultMap="studentMap" flushCache="true">
        SELECT id, name, age FROM student
    </select>
    -->
</mapper>

 

2.1.3 En SqlMapConfig.xml caché secundario abierto

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <!--这个配置使全局的映射器(二级缓存)启用或禁用缓存-->
        <setting name="cacheEnabled" value="true" />
        .....
    </settings>
    ....
</configuration>

 

2.1.4 Pruebas

caché de prueba y sqlSession no relacionada

@Test
public void testTwoCache(){
    //根据 sqlSessionFactory 产生 session
    SqlSession sqlSession1 = sessionFactory.openSession();
    SqlSession sqlSession2 = sessionFactory.openSession();
    String statement = "com.ys.twocache.UserMapper.selectUserByUserId";

    UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
    UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);

    //第一次查询,发出sql语句,并将查询的结果放入缓存中
    User u1 = userMapper1.selectUserByUserId(1);
    System.out.println(u1);
    sqlSession1.close();//第一次查询完后关闭sqlSession

    //第二次查询,即使sqlSession1已经关闭了,这次查询依然不发出sql语句
    User u2 = userMapper2.selectUserByUserId(1);
    System.out.println(u2);
    sqlSession2.close();
}

Se puede ver dos diferentes sqlSession arriba, primero apagado, la segunda consulta todavía no se emite una consulta SQL.

 

ejecución de la prueba cometer) ( operación, dos datos de la caché vacías

@Test
public void testTwoCache(){
    //根据 sqlSessionFactory 产生 session
    SqlSession sqlSession1 = sessionFactory.openSession();
    SqlSession sqlSession2 = sessionFactory.openSession();
    SqlSession sqlSession3 = sessionFactory.openSession();
    String statement = "com.ys.twocache.UserMapper.selectUserByUserId";

    UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
    UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
    UserMapper userMapper3 = sqlSession2.getMapper(UserMapper.class);

    //第一次查询,发出sql语句,并将查询的结果放入缓存中
    User u1 = userMapper1.selectUserByUserId(1);
    System.out.println(u1);
    sqlSession1.close();//第一次查询完后关闭sqlSession

    //执行更新操作,commit()
    u1.setUsername("aaa");
    userMapper3.updateUserByUserId(u1);
    sqlSession3.commit();

    //第二次查询,由于上次更新操作,缓存数据已经清空(防止数据脏读),这里必须再次发出sql语句
    User u2 = userMapper2.selectUserByUserId(1);
    System.out.println(u2);
    sqlSession2.close();
}

Ver situación de la consola:

 

 

2.1.5 Uso de resorte integrado mybatis utilizar dos caché

@CacheNamespace sólo tendrá que añadir un comentario en la abertura en el segundo nivel de caché Mapper interfaz de clase.

@CacheNamespace
public interface demoMapper {
    @Select("select * from demo")
    public List<Map<String, Object>> list();
}

 

2.2 el defecto cache secundaria

MyBatis habrá problemas caché secundario utilizado en algunos escenarios, mirada ¿Por qué dice.

Supongamos que tengo una instrucción de selección (para abrir el caché de segundo nivel):

seleccionar a.col1, a.col2, a.col3, b.col1, b.col2, b.col3 de la Tabla A a, b TableB donde a.id = b.id;

Para el funcionamiento con TableB tablaA definen en los dos Mapper, y se llaman MapperA MapperB, es decir, son dos espacios de nombres, si la caché está habilitada en este momento:

  1. MapperA en la ejecución de la sentencia SQL anterior para consultar los seis campos
  2. TableB actualizar las col1 y col2 dos campos
  3. MapperA actuar de nuevo por encima de la instrucción SQL para consultar los seis campos (la premisa no es para realizar cualquier insertar, eliminar, las operaciones de actualización)

En este punto, la pregunta es, incluso si la primera (2) de actualización paso TableB las col1 y col2 dos campos, (3) tomar la consulta caché secundaria paso MapperA a seis campo sigue siendo el valor de los originales seis campos porque CacheKey 3 conjunto de condiciones desde el punto de vista:

  1. atributo id etiqueta <select> Mapper situado Espacio de nombres + etiqueta <select>
  2. RowBounds propiedades de RowBounds offset y límite, es una clase para el procesamiento de paginación MyBatis, valores predeterminados de desplazamiento a 0, predeterminado límite Integer.MAX_VALUE
  3. <Seleccionar> etiqueta definida instrucción SQL

Para MapperA es, cualquiera de las condiciones no se cambian, se caché devuelto de forma natural los resultados originales.

El problema para el caché de segundo nivel MyBatis no es la solución de un problema, el uso de MyBatis caché secundaria tiene un requisito previo: debe asegurarse de que toda la ABM son el trabajo en el mismo espacio de nombres .

 

Por último, hablar, MyBatis soporta tres tipos de caché secundaria:

  • MyBatis caché predeterminada, el tipo está vacía, la caché es PerpetualCache
  • caché personalizado
  • el almacenamiento en caché de terceros

Resumen de : https://www.jianshu.com/p/2be932206c59
              https://www.cnblogs.com/xrq730/p/6991655.html

Publicado 54 artículos originales · ganado elogios 47 · Vistas a 10000 +

Supongo que te gusta

Origin blog.csdn.net/cy973071263/article/details/104833371
Recomendado
Clasificación