첫 번째 단계 모듈 1 Mybatis 사용자 정의 프레임 워크 노트


머리말

기사 내용의 출력 소스 : Lagou Education Java High Salary Training Camp. P7 과정
이 기사는 학습 과정의 방과 후 노트의 일부입니다.


프로젝트 주소

프로젝트 코드 :
링크 : https://pan.baidu.com/s/1pdtE7NkQb1SHQo9RnfSOTw
추출 코드 : sc4m

코드 클라우드 주소 : https://gitee.com/nie_jian_ming/njm_all_homework/tree/master/%E7%AC%AC%E4%B8%80%E9%98%B6%E6%AE%B5.%E6%A8% A1 % E5 % 9D % 97 % E4 % B8 % 80.mybatis % E4 % BD % 9C % E4 % B8 % 9A

1. 전통적인 JDBC 문제 및 사용자 정의 프레임 워크 솔루션

질문 :
1. 데이터베이스 연결을 자주 생성하고 해제하면 시스템 리소스가 낭비되어 시스템 성능에 영향을줍니다.
2. SQL 문, 매개 변수 전달 및 분석 결과 집합은 모두 하드 코딩되어 있으며 SQL 변경은 Java 코드를 변경해야하므로 코드 유지 관리가 어렵습니다.
솔루션 :
1. 데이터베이스 연결 풀을 사용하여 연결 자원을 초기화하여 자주 데이터베이스 연결을 만들고 해제하는 문제를 해결합니다.
2. xml 구성 파일로 SQL 문을 추출하고 리플렉션, 인트로 스펙 션 및 기타 기본 기술을 사용하여 엔터티와 테이블을 속성 및 필드에 자동으로 매핑하고 리플렉션을 매개 변수로 설정하고 인트로 스펙 션을 사용하여 결과를 반환합니다.
관련된 디자인 패턴 :
빌더 디자인 패턴, 수동 패턴 (세션 팩토리), 프록시 모드 (Dao 인터페이스에 대한 프록시 개체를 생성하는 JDK 동적 프록시)

2. 맞춤형 지속성 레이어 프레임 워크 디자인 아이디어

2.1. 사용자 측 (프로젝트) : 사용자 정의 지속성 계층 프레임 워크의 jar 패키지 소개

  • 구성 정보의 두 부분 : 데이터베이스 구성 정보, SQL 구성 정보 (sql 문, 매개 변수 유형, 반환 값 유형) 제공
  • 구성 파일을 사용하여 구성 정보의 다음 두 부분을 제공하십시오.
    1.sqlMapConfig.xml : 데이터베이스 구성 정보 저장, mapper.xml 가져 오기.
    2.mapper.xml : SQL 구성 정보를 저장합니다.

2.2 커스텀 지속성 레이어 프레임 워크 자체 (엔지니어링) : 본질은 JDBC를 캡슐화하는 것입니다.

2.2.1 구성 파일 읽기 :

  • 구성 파일의 경로에 따라 구성 파일을 바이트 입력 스트림으로로드하고 메모리에 저장하는 클래스를 만듭니다.
    구현 단계 : 리소스 클래스 생성,로드 메소드 : InputSteam getResourceAsSteam (String path)
    읽은 구성 정보는 작동하기 어려운 스트림 형태로 메모리에 저장됩니다. 여기서 두 개의 javaBean (컨테이너 객체)이 생성됩니다. 객체 지향적 사고를 위해. : 구성 파일의 구문 분석 된 내용을 저장하므로 나중에 액세스 할 때도 편리합니다.
    구현 단계 : 구성 클래스 2 개 생성
    구성 : 핵심 구성 클래스 : sqlMapConfig.xml에 의해 구문 분석 된 콘텐츠 저장, 데이터베이스 기본 정보 저장, Map <only ID, Mapper> 고유 ID : 네임 스페이스 + "."+ id
    MappedStatement : 매핑 구성 클래스 : mapper.xml로 구문 분석 된 콘텐츠 저장, SQL 문 저장, 명령문 유형, 입력 매개 변수 자바 유형, 출력 매개 변수 자바 유형

2.2.2 구성 파일 구문 분석 : 여기서는 dom4j를 사용하지만 다른

구현 단계 :
SqlSessionFactoryBuilder 클래스를 만든 다음 build (InputSteam in) 메서드를 만들어 세션 팩토리를 빌드합니다.
빌드 메소드에는 다음 두 가지가 구현됩니다.
1. dom4j를 사용하여 구성 파일을 구문 분석하고 구문 분석 된 내용을 컨테이너 객체로 캡슐화합니다.
2. SqlSessionFactory (공장 모드) 개체 생성, sqlSession 세션 개체 생성

2.2.3 SqlSessionFactory 인터페이스와 구현 클래스 DefaultSqlSessionFactory를 생성합니다.

그런 다음 열기 및 닫기 원칙에 따라 SqlSessionFactory 인터페이스와 구현 클래스 DefaultSqlSessionFactory를 만듭니다. sqlSession을 생성하기위한 메서드를 작성합니다.
메소드 : openSession () //
sqlSession 인터페이스 의 구현 클래스 인스턴스 객체 가져 오기 JDBC의 CRUD 메소드를 캡슐화하려면 sqlSession 인터페이스와 구현 클래스 DefaultSqlSession을 만들어야합니다.

2.2.4 Executor 인터페이스 및 구현 클래스 SimpleExecutor 구현 클래스를 만들고 JDBC 코드를 실행하기위한 쿼리 메서드를 만듭니다.

방법 : query (Configuration, MappedStatement, Object ... params);
구성 : dom4j를 사용하여 sqlMapConfig.xml을 구문 분석 할 때 구문 분석 된 콘텐츠는 다른 형식으로 Configuration 객체에 캡슐화되고 데이터베이스 구성의 정보는 내부에 저장됩니다. .
MappedStatement : dom4j를 사용하여 mapper.xml을 파싱 할 때 각 태그의 내용은 SQL 정보를 저장하는 mappingStatement 객체에 해당합니다.
Object ... params : 사용자가 전달한 매개 변수입니다. 그래서 Object ... 가변 매개 변수

3.genericTokenParserzheg 태그 파서 클래스

  1. 이 클래스는 매개 변수화 된 생성을 통해서만 생성 할 수 있습니다.
  2. genericTokenParser는 일반 토큰 파서 클래스입니다.
  3. genericTokenParser가 # {} 자리 표시자를 구문 분석 할 때 tokenHandler와 협력해야합니다.
  4. genericTokenParser의 세 가지 구성 매개 변수는 시작 태그, 종료 태그 및 태그 프로세서입니다.

4. sqlessionFactoyBuilder, sqlessionFactoy, sqlession 정보.

  1. sqlessionFactoyBuilder의 가장 좋은 범위는 로컬 메서드 변수로 정의 할 수있는 메서드 범위입니다.
  2. sqlessionFactoy의 가장 좋은 범위는 적용 범위입니다.
  3. sqlession의 가장 좋은 범위는 메서드 범위 또는 요청 범위입니다.

5. 반환 값 resultType 및 입력 매개 변수 paramterType 정보

  1. resultType의 반환 값 유형은 전체 클래스 이름 또는 별칭, 기본 데이터 유형이 허용됨, String, int 등입니다.
  2. resultType 및 resultMap의 데이터 구조는 동일하며 둘 다 맵 구조입니다.
  3. mybatis에서는 @param 주석을 사용하여 여러 매개 변수 항목을 구현하는 것 외에도 Map 객체를 사용하여 여러 매개 변수 전송을 구현할 수 있습니다.

6. mybatis의 인터페이스 개발 사양

  1. mapper.xml의 네임 스페이스는 매퍼 인터페이스의 클래스 경로와 동일합니다.
  2. 매퍼 인터페이스 메소드 이름은 mapper.xml에 정의 된 각 명령문의 ID와 동일합니다.
  3. 매퍼 인터페이스 메소드의 입력 매개 변수 유형은 mapper.xml에 정의 된 각 SQL의 parameterType 유형과 동일합니다.
  4. 매퍼 인터페이스 메소드의 출력 매개 변수 유형은 mapper.xml에 정의 된 각 SQL의 resultType 유형과 동일합니다.

7. mybatis 소스 코드 내용 정보

  1. 관련된 디자인 패턴은 에이전트 모델, 빌더 (빌더 / 생성자) 모델, 팩토리 모델, 반복자 모델입니다.
  2. 기능적 아키텍처는 인터페이스 계층, 데이터 처리 계층, 프레임 워크 지원 계층의 세 계층으로 나눌 수 있습니다.
  3. statementHandler, paramterHandle 및 resultsHandler와 같은 핵심 개체를 가로채는 플러그인 지원
  4. Executor는 SQL 생성 및 쿼리 캐시 유지 관리를 담당하는 실행자입니다.
  5. statementtHandler는 jdbc 문 (데이터베이스 SQL 실행을위한 인터페이스) 작업을 캡슐화하고 jdbc 문 작업을 담당합니다.
  6. typeHandler는 Java 데이터 유형과 jdbc 데이터 유형 간의 매핑 및 변환을 담당합니다.
  7. sqlSource는 사용자가 전달한 parameterObject에 따라 동적으로 SQL 문을 생성하고 해당 정보를 boundsql () 객체로 캡슐화합니다.

8. Mybatis 지연 로딩, 구현 원리는 무엇입니까

Mybatis는 지연로드를 지원하고
연관 객체 및 컬렉션 객체 의 지연로드지원 합니다.
연관은 일대일을 의미하고 컬렉션은 일대 다 쿼리를 의미합니다.
구성 파일에서 lazyLoadingEnabled = true | false를 활성화할지 여부를 구성 할 수 있습니다.

<settings>
    <!-- 打开延迟加载的开关 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 将积极加载改为消极加载,即延迟加载 -->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

구현 원리
CGLIB를 이용하여 타겟 객체의 프록시 객체를 생성하고, 타겟 메소드가 호출되면 인터셉터
메소드로 진입하고 데이터가 필요하면 SQL을 호출하여 DB를 조회한다.
예 : a.getB (). getName ()이 호출되면 인터셉터 invoke () 메서드는 a.getB ()가
null 값임을 확인한다음 미리 저장된 SQL을 별도로 전송하여 관련 B 객체를 쿼리합니다. , 쿼리 B. 그런 다음 a.setB (b)를 호출하여 a의 객체 b 속성이 값을 가지도록 한 다음 a.getB (). getName () 메서드 호출을 완료합니다.

9. Mybatis Executor의 세 가지 유형, 그 차이점

기본값은 SimplExcutor
SimpleExecutor입니다. 업데이트 또는 선택이 실행될 때마다 Statement 객체가 열리고 사용 직후 Statement 객체가 닫힙니다.
ReuseExecutor : 업데이트를 실행하거나 선택하고, sql을 키로 사용하여 Statement 객체를 찾고, 존재하는 경우 사용하고, 존재하지 않으면 생성합니다. 사용 후 Statement 객체는 닫히지 않고 Map에 배치됩니다. 다음 사용.
간단히 말해 Statement 객체를 재사용하는 것입니다.
BatchExecutor : 업데이트 실행 (선택 없음, JDBC 일괄 처리는 선택을 지원하지 않음), 일괄 처리에 모든 SQL 추가 addBatch (), executeBatch ()의 통합 실행을 기다립니다. 여러 Statement 객체를 캐시합니다. 각 Statement 객체는 After addBatch ( ) 완료되면 executeBatch () 일괄 처리를 하나씩 기다립니다.
JDBC 일괄 처리와 동일합니다.

작업 범위 : Executor의 이러한 특성은 SqlSession 수명주기의 범위로 엄격하게 제한됩니다.

Mybatis 구성 파일에서 기본 ExecutorType 액추에이터 유형을 지정하거나 ExecutorType 유형 매개 변수를 DefaultSqlSessionFactory의 SqlSession 생성 메소드에 수동으로 전달할 수 있습니다.

10. Mybatis의 기본 및 보조 캐시 (분산 캐싱을 구현할 수 없으며 타사 캐싱 프레임 워크가 필요함)

1. 스토리지 구조 : 첫 번째 레벨 캐시와 두 번째 레벨 캐시는 모두 HashMap 구조에 캐시됩니다.
2. 범위 : 첫
번째 수준 캐시 는 SqlSession 수준이고 범위는 SqlSession입니다. Mybatis는 기본적으로 첫 번째 수준 캐시를 설정합니다. 동일한 SqlSession에서 동일한 Sql이 쿼리 될 때 첫 번째 쿼리는 cache 데이터가 없으면 DB에서 질의하여 HashMap에 캐시하고, 두 번째 질의는 캐시에서 직접 가져오고 데이터가 있으면 DB를 확인하지 않고 직접 반환합니다.

두 번째 수준 캐시 는 매퍼 수준에 있습니다. 여러 SqlSessions는 동일한 매퍼의 SQL 문에서 작동합니다. 여러 SqlSessions는 두 번째 수준 캐시를 공유 할 수 있습니다. 두 번째 수준 캐시는 SqlSessions에 있습니다.
매퍼 아래의 sql을 처음 호출하면 정보를 조회하고 조회 한 정보는 매퍼에 해당하는 2 차 캐시 영역에 저장하고 두 번째로 네임 스페이스 아래의 매퍼 매핑 파일을 호출하면 동일한 SQL이 직접 쿼리하는 데 사용됩니다. 결과를 보조 캐시에 가져옵니다.

3. 무효화 시나리오 :
첫 번째 레벨 캐시가 추가, 삭제 또는 수정되면 캐시가 무효화됩니다.
스프링 컨테이너 관리에서 각 쿼리는 새로운 sqlSession을 생성하므로 분산 환경에서 데이터 불일치가 없습니다.

두 번째 수준 캐시를 사용하는 경우 캐시 태그를 열고 select에서 useCache 속성을 true로 추가 한 다음 업데이트 및 삭제할 때 캐시를 새로 고치도록 flushCache를 수동으로 활성화해야합니다. useCache = false가 설정되면 두 번째 레벨 캐시가 해제됩니다.

11. Mybatis 플러그인 작동 원리 및 플러그인 작성 방법

MyBatis에서 허용하는 가로 채기 방법은 다음과 같습니다.
Executor : (업데이트, 쿼리, 커밋, 롤백 등의 메서드);
SQL 구문 빌더 StatementHandler : (준비, 매개 변수화, 배치, 업데이트 쿼리 등 메서드);
매개 변수 프로세서 ParameterHandler : (getParameterObject, setParameters 메소드);
ResultSetHandler : (handleResultSets, handleOutputParameters 등 메소드);

1. 작동 원리 :
Mybatis는 Executor, StatementHandler, ParameterHandler 및 ResultSetHandler의 네 가지 인터페이스에 대한 플러그인을 작성할 수 있습니다. Mybatis는 JDK의 동적 프록시를 사용하여 인터셉트해야하는 인터페이스에 대한 프록시 객체를 생성 한 다음 인터 셉션을 구현합니다. 인터페이스의 방식이므로 실행을 가로 채야 할 때 인터페이스 방식으로 들어가면 가로 채기 방식 (AOP think)으로 들어갑니다.
2. 작성 방법 :
1. Intercepror 인터페이스의 구현 클래스를 작성하십시오
. 2. 플러그인의 서명을 설정하고, 인터셉트 할 오브젝트의 메소드를 mybatis에게 알려주십시오.
3. 마지막으로 글로벌 구성 파일에 플러그인을 등록하십시오.

예:

package com.njm.plugin;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;

import java.sql.Connection;
import java.util.Properties;


//插件签名,告诉mybatis当前插件拦截哪个对象的哪个方法
@Intercepts({  //这是个⼤花括号,也就这说这⾥可以定义多个@Signature,对多个地⽅拦截,都⽤这个拦截器
         /*
        type:表示要拦截的核心(目标)对象,拦截哪个接⼝,StatementHandler是一个sql语句构建器,用来完成sql语句预处理
        method:表示要要拦截的方法,prepare是StatementHandler里的sql预编译方法
        args:表示要拦截方法的参数,按方法里的参数顺序写,可能方法有重载,所以要通过⽅法名和⼊参来确定唯⼀。
         */
        @Signature(type = StatementHandler.class,
        method = "prepare",
        args = {Connection.class,Integer.class})
})
public class MyPlugin implements Interceptor {

    //截方法:只要被拦截的目标对象的目标方法被执行时,每次都会执行intercept方法
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        /*
         * 插件的主要功能:在执行目标方法之前,可以对sql进行修改已完成特定的功能
         * 例如增加分页功能,实际就是给sql语句添加limit;还有其他等等操作都可以
         * */
        System.out.println("对方法进行了增强。。。。。。。");
        return invocation.proceed(); //invocation.proceed():原方法执行并返回值
    }

    //主要为了把当前的拦截器生成代理存到拦截器链中,包装目标对象,为目标对象创建代理对象
    @Override
    public Object plugin(Object target) {
        //target:被拦截的目标对象,this:表示当前自定义的插件实现类,当前拦截器,也就是现在这个类,
        //wrap方法利用mybatis封装的方法为目标对象创建代理对象(没有拦截的对象会直接返回,不会创建代理对象)
        Object wrap = Plugin.wrap(target, this);
        return wrap;
    }

    //获取配置文件的参数,就是获取插件在配置文件中配置的参数值
    //插件初始化的时候调⽤,也只调⽤⼀次,插件配置的属性从这⾥设置进来
    @Override
    public void setProperties(Properties properties) {
        System.out.println("获取到的配置文件的参数是:"+properties);
    }
}

플러그인은 글로벌 구성 파일에 등록됩니다.

 <!--配置自定义插件类
        interceptor:配置类的路径
        property:配置的参数-->
    <plugins>
      <!--这个是我自定义的插件-->
		 <plugin interceptor="com.njm.plugin.MyPlugin">
		 	<property name="name" value="tom"/>
		 </plugin>
		 
        <!--这是分页插件,上面的是我自定义的插件-->
<!--        <plugin interceptor="com.github.pagehelper.PageHelper">-->
            <!--指定方言-->
<!--            <property name="dialect" value="mysql"/>-->
<!--        </plugin>-->

    </plugins>

추천

출처blog.csdn.net/weixin_39417423/article/details/108332236