(21) Mybatis 1급 조회 캐시

41120 단어 Mybatis
참고: 코드는 GitHub에 호스팅되고 주소는 다음과 같습니다.https://github.com/Damaer/Mybatis-Learning, 프로젝트는 mybatis-17-sqlsession Cache, 자체 추출이 필요합니다. 마ven 환경과 mysql 환경(sql 문구가 Resource에 있는test.sql에서)을 설정해야 합니다. 작은 별을 찍을 수 있다고 생각합니다. 반찬새는 Thanks에서 조회 캐시를 사용합니다. 주로 조회 방문 속도를 높이기 위해서입니다. 매번 데이터베이스에서 데이터를 조회하지 않아도 방문 속도를 높일 수 있습니다.그리고 데이터베이스 조회 횟수를 줄이고 데이터베이스 압력을 줄일 수 있다.
1 레벨 쿼리 캐시
1. mybatis 1급 캐시는 org 기반입니다.apache.ibatis.cache.impl.Perpetual Cache 클래스의HashMap 로컬 캐시, 역할 영역은 Sql Session이다. 즉, 같은 qlsession에서 같은 ql 조회 문장을 두 번 실행하고 첫 번째 실행이 끝난 후에 조회 결과를 캐시에 쓰고 두 번째는 캐시에서 데이터를 직접 얻으며 데이터베이스에 가서 조회할 필요가 없다.2. SqlSession이 끝나면 이 SqlSession의 캐시와 캐시가 존재하지 않습니다. mybatis는 기본적으로 1레벨 캐시를 열고 닫을 수 없습니다.1급 캐시 메모리는 sql 문장의 id에 따라 저장되며 sql의 구체적인 내용에 따라 저장되지 않습니다.
1 레벨 캐시의 존재를 증명하다
여기에 대부분의 코드를 넣지 않고 핵심 코드만 넣습니다. sql의 인터페이스는 다음과 같습니다.
public interface IStudentDao {
    public Student selectStudentById(int id);
}

mapper.xml에 대응하는 sql 문장:
    
    <select id="selectStudentById" resultType="Student">
        select * from student where id=#{xxx}

    select>

유닛 테스트:
    @Test
    public void testselectStudentById(){

        //      
        Student student=dao.selectStudentById(17);
        System.out.println(student);
        //      
        Student student2=dao.selectStudentById(17);
        System.out.println(student2);
    }

결과적으로 우리는 우리가 한 번의 조회만 실행했고 두 번째 조회를 할 때 바로 가는 1급 캐시를 볼 수 있다. 데이터베이스에 대해 조회를 하지 않았다. 만약에 데이터베이스에 대해 조회를 한다면 sql문장이 출력될 것이다.
[service] 2018-07-21 09:48:22,534 - dao.IStudentDao.selectStudentById -1349 [main] DEBUG dao.IStudentDao.selectStudentById  - ==>  Preparing: select * from student where id=? 
[service] 2018-07-21 09:48:22,635 - dao.IStudentDao.selectStudentById -1450 [main] DEBUG dao.IStudentDao.selectStudentById  - ==> Parameters: 17(Integer)
[service] 2018-07-21 09:48:22,677 - dao.IStudentDao.selectStudentById -1492 [main] DEBUG dao.IStudentDao.selectStudentById  - <==      Total: 1
Student [id=17, name=hello, age=14, score=94.6]
Student [id=17, name=hello, age=14, score=94.6]

캐시에서 데이터를 읽는 근거는 sql의 id입니까, 아니면 sql 자체입니까?
우리는 캐시가 도대체 무엇에 따라 캐시를 하는지 의문이 생겼다. 그러면 우리는 실험을 해야 한다. 서로 다른 id를 가지고 있지만 ql가 완전히 일치하는 두 개의 ql를 쓰면 결과를 알 수 있다.다음은 같은 namespace에서 진행됩니다: sql 인터페이스:
public interface IStudentDao {
    public Student selectStudentById(int id);
    //      id sql
    public Student selectStudentById2(int id);
}

mapper 파일:



<mapper namespace="dao.IStudentDao">

    
    <select id="selectStudentById" resultType="Student">
        select * from student where id=#{xxx}

    select>

    
    <select id="selectStudentById2" resultType="Student">
        select * from student where id=#{xxx}

    select>
mapper>

테스트 코드:
    @Test
    public void testDiffereentId2(){

        //      
        Student student=dao.selectStudentById(17);
        System.out.println(student);
        //      ,     id,   namespace
        Student student2=dao.selectStudentById2(17);
        System.out.println(student2);
    }

결과는 다음과 같다. 우리는 안에서 두 번의 sql를 실행한 것을 볼 수 있다. 그러면 1급 캐시가 sql 자체에 근거한 것이 아니라 sql의 id 캐시에 근거한 것이다.
[service] 2018-07-21 10:26:32,844 - dao.IStudentDao.selectStudentById -957  [main] DEBUG dao.IStudentDao.selectStudentById  - ==>  Preparing: select * from student where id=? 
[service] 2018-07-21 10:26:32,954 - dao.IStudentDao.selectStudentById -1067 [main] DEBUG dao.IStudentDao.selectStudentById  - ==> Parameters: 17(Integer)
[service] 2018-07-21 10:26:32,989 - dao.IStudentDao.selectStudentById -1102 [main] DEBUG dao.IStudentDao.selectStudentById  - <==      Total: 1
Student [id=17, name=hello, age=14, score=94.6]
[service] 2018-07-21 10:26:32,990 - dao.IStudentDao.selectStudentById2 -1103 [main] DEBUG dao.IStudentDao.selectStudentById2  - ==>  Preparing: select * from student where id=? 
[service] 2018-07-21 10:26:32,991 - dao.IStudentDao.selectStudentById2 -1104 [main] DEBUG dao.IStudentDao.selectStudentById2  - ==> Parameters: 17(Integer)
[service] 2018-07-21 10:26:32,996 - dao.IStudentDao.selectStudentById2 -1109 [main] DEBUG dao.IStudentDao.selectStudentById2  - <==      Total: 1
Student [id=17, name=hello, age=14, score=94.6]

다른 Namespace의 같은 id는?
다른 Namespace.같은 id라도 1급 캐시가 적용되지 않습니다. 왜냐하면 sql 캐시는namespace에 따라 구분되기 때문입니다.두 개의 ql 인터페이스는 다음과 같습니다.
public interface IStudentDao {
    public Student selectStudentById(int id);
}

public interface IStudentDao2 {
    //   namespace    id   
    public Student selectStudentById(int id);
}

두 개의 마퍼 파일은 다음과 같습니다.

        
        
<mapper namespace="dao.IStudentDao">

<select id="selectStudentById" resultType="Student">
    select * from student where id=#{xxx}
select>
mapper>



<mapper namespace="dao.IStudentDao2">
    
    <select id="selectStudentById" resultType="Student">
        select * from student where id=#{xxx}
    select>

mapper>

유닛 테스트는 다음과 같습니다.
    @Test
    public void testDiffereentNamespaceSameId(){

        //      
        Student student=dao.selectStudentById(17);
        System.out.println(student);
        //      ,     id,   namespace
        IStudentDao2 dao2= sqlSession.getMapper(IStudentDao2.class);
        Student student2=dao2.selectStudentById(17);
        System.out.println(student2);
    }

결과는 다음과 같습니다. 우리는 sql를 두 번 실행한 것을 볼 수 있습니다.또한 1급 캐시가 같은namespace 아래의 같은 id에 근거하고 있다는 것을 증명했다. 같은 id라고 해도namespace는 효력이 발생하지 않는다. 왜냐하면 1급 캐시는namespace에 따라 저장을 구분하기 때문이다.
[service] 2018-07-21 10:37:36,916 - dao.IStudentDao.selectStudentById -1545 [main] DEBUG dao.IStudentDao.selectStudentById  - ==>  Preparing: select * from student where id=? 
[service] 2018-07-21 10:37:37,154 - dao.IStudentDao.selectStudentById -1783 [main] DEBUG dao.IStudentDao.selectStudentById  - ==> Parameters: 17(Integer)
[service] 2018-07-21 10:37:37,194 - dao.IStudentDao.selectStudentById -1823 [main] DEBUG dao.IStudentDao.selectStudentById  - <==      Total: 1
Student [id=17, name=hello, age=14, score=94.6]
[service] 2018-07-21 10:37:37,202 - dao.IStudentDao2.selectStudentById -1831 [main] DEBUG dao.IStudentDao2.selectStudentById  - ==>  Preparing: select * from student where id=? 
[service] 2018-07-21 10:37:37,204 - dao.IStudentDao2.selectStudentById -1833 [main] DEBUG dao.IStudentDao2.selectStudentById  - ==> Parameters: 17(Integer)
[service] 2018-07-21 10:37:37,210 - dao.IStudentDao2.selectStudentById -1839 [main] DEBUG dao.IStudentDao2.selectStudentById  - <==      Total: 1
Student [id=17, name=hello, age=14, score=94.6]

1급 캐시에 대한 추가 삭제의 영향
sqlsession을 제출하든지 말든지, 삭제 수정 작업을 추가합니다.commit () 는 쿼리 캐시와 쿼리 캐시를 모두 지우고 쿼리 캐시를 DB에서 다시 쿼리합니다.ql 인터페이스는 다음과 같습니다.
public interface IStudentDao {
    public Student selectStudentById(int id);
    //      id sql
    public Student selectStudentById2(int id);


    //     
    public void insertStudent(Student student);
    //   id    
    public void deleteStudentById(int id);
    //        
    public void updateStudent(Student student);
}

mapper.xml 파일:



<mapper namespace="dao.IStudentDao">

    
    <select id="selectStudentById" resultType="Student">
        select * from student where id=#{xxx}

    select>

    
    <select id="selectStudentById2" resultType="Student">
        select * from student where id=#{xxx}
select>

    <insert id="insertStudent" parameterType="Student">
        insert into student(name,age,score) values(#{name},#{age},#{score})
    insert>
    
    <delete id="deleteStudentById">
        delete from student where id=#{id}
        
    delete>

    <update id="updateStudent">
        update student set name=#{name},age=#{age},score=#{score} where id=#{id}
    update>
mapper>

유닛 테스트:
    public void test03(){

        //      
        Student student=dao.selectStudentById(17);
        System.out.println(student);
        //    
        Student student1 = new Student("12112",12,21.6);
        //dao.insertStudent(student1);
        dao.updateStudent(student1);
        student=dao.selectStudentById(17);
        System.out.println(student);
    }

첫 번째 질의를 수행한 후 삽입 작업을 수행하면 다음과 같은 수준의 캐시가 업데이트됩니다.
[service] 2018-07-21 13:07:27,136 - dao.IStudentDao.selectStudentById -1059 [main] DEBUG dao.IStudentDao.selectStudentById  - ==>  Preparing: select * from student where id=? 
[service] 2018-07-21 13:07:27,247 - dao.IStudentDao.selectStudentById -1170 [main] DEBUG dao.IStudentDao.selectStudentById  - ==> Parameters: 17(Integer)
[service] 2018-07-21 13:07:27,288 - dao.IStudentDao.selectStudentById -1211 [main] DEBUG dao.IStudentDao.selectStudentById  - <==      Total: 1
Student [id=17, name=hello, age=14, score=94.6]
[service] 2018-07-21 13:07:27,289 - dao.IStudentDao.insertStudent -1212 [main] DEBUG dao.IStudentDao.insertStudent  - ==>  Preparing: insert into student(name,age,score) values(?,?,?) 
[service] 2018-07-21 13:07:27,291 - dao.IStudentDao.insertStudent -1214 [main] DEBUG dao.IStudentDao.insertStudent  - ==> Parameters: 12112(String), 12(Integer), 21.6(Double)
[service] 2018-07-21 13:07:27,295 - dao.IStudentDao.insertStudent -1218 [main] DEBUG dao.IStudentDao.insertStudent  - <==    Updates: 1
[service] 2018-07-21 13:07:27,295 - dao.IStudentDao.selectStudentById -1218 [main] DEBUG dao.IStudentDao.selectStudentById  - ==>  Preparing: select * from student where id=? 
[service] 2018-07-21 13:07:27,295 - dao.IStudentDao.selectStudentById -1218 [main] DEBUG dao.IStudentDao.selectStudentById  - ==> Parameters: 17(Integer)
[service] 2018-07-21 13:07:27,302 - dao.IStudentDao.selectStudentById -1225 [main] DEBUG dao.IStudentDao.selectStudentById  - <==      Total: 1
Student [id=17, name=hello, age=14, score=94.6]

첫 번째 쿼리를 수행한 후 다시 업데이트 작업을 수행합니다. 쿼리 데이터가 아니더라도 같은 테이블에 속하고 1레벨 캐시가 업데이트됩니다.
[service] 2018-07-21 23:43:28,073 - dao.IStudentDao.selectStudentById -1081 [main] DEBUG dao.IStudentDao.selectStudentById  - ==>  Preparing: select * from student where id=? 
[service] 2018-07-21 23:43:28,202 - dao.IStudentDao.selectStudentById -1210 [main] DEBUG dao.IStudentDao.selectStudentById  - ==> Parameters: 17(Integer)
[service] 2018-07-21 23:43:28,236 - dao.IStudentDao.selectStudentById -1244 [main] DEBUG dao.IStudentDao.selectStudentById  - <==      Total: 1
Student [id=17, name=hello, age=14, score=94.6]
[service] 2018-07-21 23:43:28,239 - dao.IStudentDao.updateStudent -1247 [main] DEBUG dao.IStudentDao.updateStudent  - ==>  Preparing: update student set name=?,age=?,score=? where id=? 
[service] 2018-07-21 23:43:28,241 - dao.IStudentDao.updateStudent -1249 [main] DEBUG dao.IStudentDao.updateStudent  - ==> Parameters: 12112(String), 12(Integer), 21.6(Double), 18(Integer)
[service] 2018-07-21 23:43:28,246 - dao.IStudentDao.updateStudent -1254 [main] DEBUG dao.IStudentDao.updateStudent  - <==    Updates: 1
[service] 2018-07-21 23:43:28,246 - dao.IStudentDao.selectStudentById -1254 [main] DEBUG dao.IStudentDao.selectStudentById  - ==>  Preparing: select * from student where id=? 
[service] 2018-07-21 23:43:28,246 - dao.IStudentDao.selectStudentById -1254 [main] DEBUG dao.IStudentDao.selectStudentById  - ==> Parameters: 17(Integer)
[service] 2018-07-21 23:43:28,251 - dao.IStudentDao.selectStudentById -1259 [main] DEBUG dao.IStudentDao.selectStudentById  - <==      Total: 1
Student [id=17, name=hello, age=14, score=94.6]

쿼리 작업을 수행한 후 삭제 작업을 수행하면 레벨1 캐시도 업데이트됩니다.
[service] 2018-07-21 23:44:49,296 - dao.IStudentDao.selectStudentById -1172 [main] DEBUG dao.IStudentDao.selectStudentById  - ==>  Preparing: select * from student where id=? 
[service] 2018-07-21 23:44:49,457 - dao.IStudentDao.selectStudentById -1333 [main] DEBUG dao.IStudentDao.selectStudentById  - ==> Parameters: 17(Integer)
[service] 2018-07-21 23:44:49,504 - dao.IStudentDao.selectStudentById -1380 [main] DEBUG dao.IStudentDao.selectStudentById  - <==      Total: 1
Student [id=17, name=hello, age=14, score=94.6]
[service] 2018-07-21 23:44:49,505 - dao.IStudentDao.deleteStudentById -1381 [main] DEBUG dao.IStudentDao.deleteStudentById  - ==>  Preparing: delete from student where id=? 
[service] 2018-07-21 23:44:49,505 - dao.IStudentDao.deleteStudentById -1381 [main] DEBUG dao.IStudentDao.deleteStudentById  - ==> Parameters: 18(Integer)
[service] 2018-07-21 23:44:49,508 - dao.IStudentDao.deleteStudentById -1384 [main] DEBUG dao.IStudentDao.deleteStudentById  - <==    Updates: 1
[service] 2018-07-21 23:44:49,509 - dao.IStudentDao.selectStudentById -1385 [main] DEBUG dao.IStudentDao.selectStudentById  - ==>  Preparing: select * from student where id=? 
[service] 2018-07-21 23:44:49,509 - dao.IStudentDao.selectStudentById -1385 [main] DEBUG dao.IStudentDao.selectStudentById  - ==> Parameters: 17(Integer)
[service] 2018-07-21 23:44:49,517 - dao.IStudentDao.selectStudentById -1393 [main] DEBUG dao.IStudentDao.selectStudentById  - <==      Total: 1
Student [id=17, name=hello, age=14, score=94.6]

좋은 웹페이지 즐겨찾기