머리말
mybatis 레벨 2 캐시 란 무엇입니까?
보조 캐시는 여러 sqlsessions에서 공유되며 그 범위는 Mapper의 동일한 네임 스페이스입니다.
즉, 다른 SQLSESSIONS에서 동일한 네임 스페이스에서 동일한 SQL 문 및 SQL 템플릿의 매개 변수도 동일하며 캐시가 적용됩니다.
첫 번째 실행 후 데이터베이스에서 쿼리 된 데이터는 캐시에 기록되며 캐시에서 데이터가 더 이상 데이터베이스에서 쿼리되지 않아 쿼리 효율성이 향상됩니다.
Mybatis는 기본적으로 보조 캐시를 활성화하지 않으며 Global Configuration (Mybatis-config.xml)에서 보조 캐시를 활성화해야합니다.
이 기사에서는 SpringBoot 및 Mybatis와 통합하기위한 캐시로 Redis를 사용하는 방법에 대해 설명합니다.
1. POM 의존성
Springboot Redis 통합 패키지를 사용하여 Redis에 대한 액세스를 용이하게하십시오. Jedis는 Redis 클라이언트에서 사용됩니다.
또한 KV 캐시 읽기 및 쓰기는 직렬화되므로 직렬화 패키지가 소개됩니다.
<pectionency> <groupId> org.springframework.boot </groupid> <artifactid> Spring-Boot-Starter-Redis </artifactid> </fectionency> <groupidency> <groupid> redis.clients </groupid> <artifactid> jedis </artifactid> 2.8.0 </dependency> </dependency> <groupid> com.alibaba </groupid> <artifactid> fastjson </artifactid> <bersion> 1.2.19 </version> </fectionency>
종속성이 완료되면 다음 단계는 Redis 클라이언트를 조정하는 것입니다.
2. Redis Access에서 사용하는 콩
구성을 추가하고 JedisconnectionFactory Bean을 구성하고 나중에 사용하도록 남겨 두십시오.
일반적으로, Redistemplate Bean도 생성되지만 다음 시나리오에서는 사용되지 않습니다.
@ConfigurationPublic Class readisconfig {@value ( "$ {spring.redis.host}") 개인 문자열 호스트; // 공간은 제한되어 있습니다. @Bean public jedispoolconfig getRedisconfig () {jedispoolconfig config = new jedispoolconfig (); config.setmaxidle (maxidle); config.setmaxtotal (maxtotal); config.setmaxwaitmillis (Maxwaitmillis); config.setminidle (minidle); 반환 구성; } @Bean (이름 = "JediscOntectionFactory") public jedisconnectionFactory getConnectionFactory () {jedisconnectionFactory Factory = New JedisconnectionFactory (); jedispoolconfig config = getRedisconfig (); Factory.setpoolconfig (config); Factory.SethostName (호스트); Factory.Setport (포트); Factory.SetDatabase (데이터베이스); Factory.SetPassword (비밀번호); Factory.SetTimeout (타임 아웃); 반품 공장; } @Bean (name = "redistemplate") public redistemplate <?,?> getRedistemplate () {redistemplate <?,?> template = new StringRedistemplate (getConnectionFactory ()); 리턴 템플릿; }}여기에서 @Value는 Redis 관련 구성을 읽는 데 사용되며 더 간단한 구성 읽기 방법 (@ConfigurationProperties (prefix = ...))가 있습니다.
Redis 관련 구성은 다음과 같습니다
#redisspring.redis.host = 10.93.84.53spring.redis.port = 6379spring.redis.password = bigdata123spring.redis.database = 15spring.redis. 타임 아웃 = 0Spring.redis.pool.maxtotal = 8Spring.redis.pool.maxwaitmillis = 1000Spring.redis.pool.maxidle = 8spring.redis.pool.minidle = 0
Redis 클라이언트의 구성 의미는 여기에 설명되지 않습니다. 풀 관련은 일반적으로 성능과 관련이 있으며 동시 핸들, 메모리 및 기타 리소스의 동시성에 따라 설정해야합니다.
Redis 클라이언트가 설정되었으며 Redis를 MyBatis의 캐시로 구성하기 시작합니다.
3. Mybatis 캐시
이 단계는 가장 중요한 단계입니다. 구현 방법은 mybatis의 인터페이스 org.apache.ibatis.cache.cache를 구현하는 것입니다.
이 인터페이스는 쓰기 캐시, 캐시 읽기, 캐시 파괴 및 액세스 제어 읽기 및 쓰기 잠금을 설계합니다.
캐시 인터페이스를 구현하기 위해 구현하는 클래스는 MyBatisRediscache입니다.
mybatisrediscache.java
공개 클래스 MyBatisRediscache CACHE {private static jedisconnection factory jedisconnection factory; 개인 최종 문자열 ID; 개인 최종 readWritElock readWritelock = 새로운 ReentrantreadWritelock (); public mybatisrediscache (Final String ID) {if (id == null) {새로운 불법 불법 행위 ( "캐시 인스턴스가 ID가 필요"); } this.id = id; } @override public void clear () {readisconnection connection = null; try {connection = jedisconnectionfactory.getConnection (); Connection.flushdb (); Connection.flushall (); } catch (jedisconnectionException e) {e.printstacktrace (); } 마침내 {if (connection! = null) {connection.close (); }}} @override public string getId () {return this.id; } @override public Object getObject (Object Key) {Object result = null; REASISCONCINET CONNECTION = NULL; try {connection = jedisconnectionfactory.getConnection (); Redisserializer <bood> Serializer = New JDKSerializationRedisserializer (); result = serializer.deserialize (connection.get (serializer.serialize (key))); } catch (jedisconnectionException e) {e.printstacktrace (); } 마침내 {if (connection! = null) {connection.close (); }} 반환 결과; } @override public readWritelock getReadWritElock () {return this.ReadWritElock; } @override public int getsize () {int result = 0; REASISCONCINET CONNECTION = NULL; try {connection = jedisconnectionfactory.getConnection (); 결과 = integer.valueof (connection.dbsize (). toString ()); } catch (jedisconnectionException e) {e.printstacktrace (); } 마침내 {if (connection! = null) {connection.close (); }} 반환 결과; } @override public void putobject (객체 키, 개체 값) {readisconnection connection = null; try {connection = jedisconnectionfactory.getConnection (); Redisserializer <bood> Serializer = New JDKSerializationRedisserializer (); Connection.set (Serializer.serialize (키), Serializer.serialize (value)); } catch (jedisconnectionException e) {e.printstacktrace (); } 마침내 {if (connection! = null) {connection.close (); }}} @override public object removeObject (객체 키) {readisconnection connection = null; 객체 결과 = null; try {connection = jedisconnectionfactory.getConnection (); Redisserializer <bood> Serializer = New JDKSerializationRedisserializer (); result = connection.expire (Serializer.serialize (키), 0); } catch (jedisconnectionException e) {e.printstacktrace (); } 마침내 {if (connection! = null) {connection.close (); }} 반환 결과; } public static void setjedisconnectionfactory (jediscontectory jedisconnectionfactory) {mybatisrediscache.jedisconnectionfactory = jedisconnection factory; }}알아채다:
보시다시피,이 클래스는 Spring Virtual Machine에서 관리하는 클래스가 아니지만 스프링 빈을 주입 해야하는 정적 속성 JedisconnectionFactory가 있습니다.
일반 클래스에서 Spring ContextAware는 일반적으로 SpringBoot 내장 SpringContextAware를 사용하는 데 사용됩니다.
여기서는 다른 방법 인 정적 주입이 사용됩니다. 이 방법은 readiscaceretransfer를 통해 구현됩니다.
4. 정적 주입
readiscachetransfer.java
@ComponentPublic 클래스 RESISCACHETRANSFER {@autowired public void setJedisconnectionFactory (jediscontectionFactory jedisconnectionFactory) {myBatisRediscache.SetJediscOntectionFactory (jediscOntectionFactory); }}readiscachetransfer는 스프링 부트 콩이라는 것을 알 수 있습니다. 창조가 시작될 때 컨테이너를 초기화 할 때 JedisconnectionFactory Bean은 SetJedisconnectionFactory 방법의 전달 매개 변수에 주입됩니다.
SetJedisconnectionFactory는 정적 메소드를 호출하여 클래스 MyBatisRediscache의 정적 속성을 설정합니다.
이것은 스프링 컨테이너가 관리하는 Jedisconnection factory를 정적 도메인에 주입합니다.
이 시점에서 코드는 기본적으로 완료되었으며 다음은 일부 구성입니다. 주요 것은 (1) 글로벌 스위치; (2) 네임 스페이스 범위 스위치; (3) 모델 인스턴스 직렬화.
5. MyBatis 레벨 2 캐시의 전역 스위치
앞에서 언급했듯이 기본 레벨 2 캐시가 켜지지 않으며 True로 설정해야합니다. 이것은 글로벌 레벨 2 캐시의 스위치입니다.
Mybatis 글로벌 구성.
<? xml version = "1.0"alcoding = "utf-8"?> <! doctype configuration public "-// mybatis.org//dtd config 3.0 // en" "http://mybatis.org/dtd/mybatis-3-config.dtd "> configuration>-글로벌 매개 변수-<! 캐시를 활성화 또는 비활성화합니다. -> <setting name = "cacheenabled"value = "true"/> </settings> </configuration>
데이터 소스에서 글로벌 구성의로드는 다음과 같습니다.
bean.setMapperLocations (new PathMatchingResourcepatternresolver (). getResources ( "classpath : mybatis-mapper/*. xml");
mapper.xml의 저장 경로를 지정합니다. mybatis-mapper 경로에서 .xml이있는 모든 접미사를 읽습니다.
bean.setConfigLocation (새로운 classPathResource ( "mybatis-config.xml"));
mybatis-config.xml의 저장 경로는 지정되어 리소스 디렉토리에 직접 배치됩니다.
@Bean (이름 = "moonlightsqlsessionFactory") @Primary public public sqlsessionFactory moonlightsqlsessionFactory (@Qualifier ( "MoonlightData") DataSource DataSource) 예외 {sqlsession actorybean bean = new sqlsession actorcorybean (); Bean.SetDatasource (DataSource); bean.setMapperLocations (new PathMatchingResourcepatternresolver (). getResources ( "classpath : mybatis-mapper/*. xml"); bean.setConfigLocation (새로운 classPathResource ( "mybatis-config.xml")); return bean.getObject (); }6. Mapper 스코프 네임 스페이스를 구성하십시오
앞에서 언급했듯이 보조 캐시의 범위는 맵퍼 네임 스페이스 이므로이 구성은 맵퍼에 작성해야합니다.
<Mapper 네임 스페이스 = "com.kangaroo.studio.moonlight.dao.mapper.moonlightmapper"> <cache type = "com.kangaroo.studio.moonlight.dao.cache.mybatisrediscache"/<resultmap id = "geofencelist" type = "com.kangaroo.studio.moonlight.dao.model.geofence"> <constructor> <idarg column = "id"javatype = "java.lang.integer"jdbctype = "integer" /> <arg column = "javatype ="java.lang.string "jdbctype ="java.lang. column = "type"javatype = "java.lang.integer"jdbctype = "integer" /<arg column = "group"javatype = "java.lang.string"jdbctype = "varchar" /<arg column = "geo"java.lang.string "jdbctype"jdbctype 열 = "CreateTime"javatype = "java.lang.string"jdbctype = "varchar" /> <arg column = "updateTime"javatype = "java.lang.string"jdbctype = "varchar" /> < /constructor> < /resultmap> <select id = "querygeofence" parametertype = "com.kangaroo.studio.moonlight.dao.model.geofenceQueryParam"resultMap = "GeofenCElist"> repid = "base_column"/> geofence inge refid = "base_column"/> here 1 = 1 <test = "type! = null"> 및 type = #if test = if test = if test = if test = if test = if test = if test = if test = if test = #if test = if test = if test = if test = #if test = #null " #null"입니다. concat ( '%', #{name}, '%') </if> <if test = "group! = null"> 및`group` kok` kok concat ( '%', #{group}, '%') </if> < "startTime! = null"> 및 createTime> = #{startTime} </if> if test> = null "> 및 createTime} </if> </select> </mapper>알아채다:
네임 스페이스의 캐시 태그는 캐시로드 구성이며 캐시 사용은 공식적으로 우리가 구현 한 mybatisrediscache에 의해 구현됩니다.
<캐시 타입 = "com.kangaroo.studio.moonlight.dao.cache.mybatisrediscache"/>
여기에는 쿼리 쿼리 게인 만 구현됩니다. 선택 태그 에서이 SQL의 캐시를 켜거나 끌 수 있습니다. 속성 값 usecache = true/false를 사용하십시오.
7. 맵퍼와 모델
캐시 모델 읽기 및 쓰기 작업은 직렬화되어야합니다. 클래스가 선언 될 때만 혈청 지정된 인터페이스 만 구현하면됩니다.
공공 클래스 지오 페인은 직렬화 가능 {// setter and getter avisted} 공개 클래스 지오 펜스 파람 (GeofenceParam) 시리얼화할 수있는 {// setter and getter 생략}을 구현합니다.Mapper는 여전히 이전과 동일합니다. mapper.xml을 사용하는 경우 추상 기능 만 정의하면됩니다.
@MapperPublic 인터페이스 MoonlightMapper {List <Geofence> QueryGeofence (GeofenceQueryParam GeofenceQueryParam);}이 시점에서 모든 코드와 구성이 완료되면 아래에서 테스트합시다.
8. 테스트하십시오
이러한 인터페이스 게시물은 컨트롤러에서 구현됩니다.
@RequestMapping (value = "/fence/query", method = requestmethod.post) @ResponseBody public responsentity <sponept> queryfence (@requestbody geofencequeryparam geofencequeryparam) {integer pagenum = geofencequeryparam.getpagenum (null?) integer pagesize = geofencequeryparam.getPagesize ()! = null? geofencequeryparam.getPagesize () : 10; pageHelper.startPage (pagenum, pagesize); 목록 <geofence> list = moonlightmapper.querygeofence (GeofenceQueryParam); New Responsentity <> (새로운 응답 (resultCode.Success, "Query Geofence Success", List), httpstatus.ok); } catch (예외 e) {logger.error ( "Query Geofence 실패", e); 새로운 응답 entity <> (new response (resultCode.Exception, "Query Geofence 실패", null), httpstatus.internal_server_error); }컬을 사용하여 요청을 보내십시오
1) -h- 컨텐츠 유형 : 응용 프로그램/JSON 메소드
2) -d- 다음은 JSON 형식의 매개 변수 패키지입니다.
curl -h "content -type : application/json"-xpost http : //. . . /moonlight/fence/query -d '{ "name": "test", "test", "Group": "Test", "Type": "StartTime": "2017-12-06 00:00:00", "EndTime": "2017-12-06 16:00:00", "pagenum": "Pagesize": 8 "세 번 요청하면 로그는 다음과 같이 인쇄됩니다
보시다시피, 처음으로 SQL 템플릿 쿼리가 실행되고 캐시가 발생했을 때만.
테스트 환경에서 비교적 적은 양의 데이터로 인해 쿼리 속도의 캐시 최적화는 분명하지 않습니다. 나는 여기에 많이 설명하지 않을 것입니다.