기사 디렉토리
- 머리말
- 프로젝트 주소
- 1. 전통적인 JDBC 문제 및 사용자 정의 프레임 워크 솔루션
- 2. 맞춤형 지속성 레이어 프레임 워크 디자인 아이디어
- 3.genericTokenParserzheg 태그 파서 클래스
- 4. sqlessionFactoyBuilder, sqlessionFactoy, sqlession 정보.
- 5. 반환 값 resultType 및 입력 매개 변수 paramterType 정보
- 6. mybatis의 인터페이스 개발 사양
- 7. mybatis 소스 코드 내용 정보
- 8. Mybatis 지연 로딩, 구현 원리는 무엇입니까
- 9. Mybatis Executor의 세 가지 유형, 그 차이점
- 10. Mybatis의 기본 및 보조 캐시 (분산 캐싱을 구현할 수 없으며 타사 캐싱 프레임 워크가 필요함)
- 11. Mybatis 플러그인 작동 원리 및 플러그인 작성 방법
머리말
기사 내용의 출력 소스 : Lagou Education Java High Salary Training Camp. P7 과정
이 기사는 학습 과정의 방과 후 노트의 일부입니다.
프로젝트 주소
프로젝트 코드 :
링크 : https://pan.baidu.com/s/1pdtE7NkQb1SHQo9RnfSOTw
추출 코드 : sc4m
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 태그 파서 클래스
- 이 클래스는 매개 변수화 된 생성을 통해서만 생성 할 수 있습니다.
- genericTokenParser는 일반 토큰 파서 클래스입니다.
- genericTokenParser가 # {} 자리 표시자를 구문 분석 할 때 tokenHandler와 협력해야합니다.
- genericTokenParser의 세 가지 구성 매개 변수는 시작 태그, 종료 태그 및 태그 프로세서입니다.
4. sqlessionFactoyBuilder, sqlessionFactoy, sqlession 정보.
- sqlessionFactoyBuilder의 가장 좋은 범위는 로컬 메서드 변수로 정의 할 수있는 메서드 범위입니다.
- sqlessionFactoy의 가장 좋은 범위는 적용 범위입니다.
- sqlession의 가장 좋은 범위는 메서드 범위 또는 요청 범위입니다.
5. 반환 값 resultType 및 입력 매개 변수 paramterType 정보
- resultType의 반환 값 유형은 전체 클래스 이름 또는 별칭, 기본 데이터 유형이 허용됨, String, int 등입니다.
- resultType 및 resultMap의 데이터 구조는 동일하며 둘 다 맵 구조입니다.
- mybatis에서는 @param 주석을 사용하여 여러 매개 변수 항목을 구현하는 것 외에도 Map 객체를 사용하여 여러 매개 변수 전송을 구현할 수 있습니다.
6. mybatis의 인터페이스 개발 사양
- mapper.xml의 네임 스페이스는 매퍼 인터페이스의 클래스 경로와 동일합니다.
- 매퍼 인터페이스 메소드 이름은 mapper.xml에 정의 된 각 명령문의 ID와 동일합니다.
- 매퍼 인터페이스 메소드의 입력 매개 변수 유형은 mapper.xml에 정의 된 각 SQL의 parameterType 유형과 동일합니다.
- 매퍼 인터페이스 메소드의 출력 매개 변수 유형은 mapper.xml에 정의 된 각 SQL의 resultType 유형과 동일합니다.
7. mybatis 소스 코드 내용 정보
- 관련된 디자인 패턴은 에이전트 모델, 빌더 (빌더 / 생성자) 모델, 팩토리 모델, 반복자 모델입니다.
- 기능적 아키텍처는 인터페이스 계층, 데이터 처리 계층, 프레임 워크 지원 계층의 세 계층으로 나눌 수 있습니다.
- statementHandler, paramterHandle 및 resultsHandler와 같은 핵심 개체를 가로채는 플러그인 지원
- Executor는 SQL 생성 및 쿼리 캐시 유지 관리를 담당하는 실행자입니다.
- statementtHandler는 jdbc 문 (데이터베이스 SQL 실행을위한 인터페이스) 작업을 캡슐화하고 jdbc 문 작업을 담당합니다.
- typeHandler는 Java 데이터 유형과 jdbc 데이터 유형 간의 매핑 및 변환을 담당합니다.
- 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>