序文
MyBatisレベル2キャッシュとは何ですか?
セカンダリキャッシュは複数のSQLSessionsで共有され、そのスコープはマッパーの同じ名前空間です。
つまり、異なるsqlsessionsでは、同じ名前空間の下で同じSQLステートメントであり、SQLテンプレートのパラメーターも同じであり、キャッシュがヒットします。
最初の実行の後、データベースに照会されたデータがキャッシュに書き込まれ、データがデータベースからクエリされなくなるため、クエリ効率が向上します。
MyBatisはデフォルトでセカンダリキャッシュを有効にしないため、グローバル構成(MyBatis-Config.xml)でセカンダリキャッシュを有効にする必要があります。
この記事では、Redisをキャッシュとして使用してSpringbootおよびMyBatisと統合する方法について説明します。
1。POM依存関係
Redisへのアクセスを容易にするために、Springboot Redis Integration Packageを使用します。 JedisはRedisクライアントで使用されます。
さらに、読み取りと書き込みKVキャッシュがシリアル化されるため、シリアル化パッケージが導入されます。
<Dependency> groupId> org.springframework.boot </groupid> <artifactid> spring-boot-starter-redis </artifactid> </dependency> <dependency> groupid> redis.clients </groupId> <artifactid> jedis </artifactid> <バージョン<GroupId> com.alibaba </groupId> <artifactid> fastjson </artifactid> <バージョン> 1.2.19 </version> </dependency>
依存関係が完了した後、次のステップはRedisクライアントを調整することです。
2。Redisアクセスで使用される豆
構成を追加し、JedisconnectionFactory Beanを構成し、後で使用するようにします。
一般的に言えば、Redistemplate Beanも生成されますが、次のシナリオでは使用されません。
@configurationPublic Class Redisconfig {@value( "$ {spring.redis.host}")private string host; //スペースは限られています、@Bean Public JedisPoolConfig getRedisconfig(){jedispoolconfig config = new JedisPoolConfig(); config.setmaxidle(maxidle); config.setmaxtotal(maxtotal); config.setmaxwaitmillis(maxwaitmillis); config.setminidle(minidle); configを返します。 } @bean(name = "jedisconnectionfactory")public jedisconnectionfactory getConnectionFactory(){jedisconnectionFactory = new JedisconnectionFactory(); jedispoolconfig config = getredisconfig(); Factory.setPoolConfig(config); Factory.sethostname(host); Factory.setport(ポート); Factory.setDatabase(データベース); Factory.SetPassWord(パスワード); Factory.settimeout(Timeout);ファクトリーを返します。 } @bean(name = "redistemplate")public redistemplate <?、?テンプレートを返します。 }}ここでは、@valueはRedis関連の構成の読み取りに使用され、よりシンプルな構成読み取り方法(@configurationProperties(prefix = ...))があり、試してみることができます。
Redis関連の構成は次のとおりです
#redisspring.redis.host = 10.93.84.53spring.redis.port = 6379spring.redis.password = bigdata123spring.redis.database = 15spring.redis。 Timeout = 0SPRING.REDIS.POOL.MAXTOTAL = 8SPRING.REDIS.POOL.MAXWAITMILLIS = 1000SPRING.REDIS.POOL.MAXIDLE = 8SPRING.REDIS.POOL.MINIDLE = 0
Redisクライアントの構成の意味については、ここでは説明しません。プール関連は一般にパフォーマンスに関連しており、ハンドル、メモリ、その他のリソースの並行性量に基づいて設定する必要があります。
Redisクライアントがセットアップされており、MyBatisのキャッシュとしてRedisの構成を開始します。
3。MyBatisキャッシュ
このステップは最も重要なステップです。実装方法は、MyBatisのインターフェイスorg.apache.ibatis.cache.cacheを実装することです。
このインターフェイスは、キャッシュの書き込み、キャッシュの読み取り、キャッシュを破壊し、読み取りと書き込みロックを設計します。
キャッシュインターフェイスを実装するために実装するクラスは、MyBatiSrediscacheです。
mybatisrediscache.java
パブリッククラスmybatisrediscacheはキャッシュを実装します{private static jedisconnectionfactory jedisconnectionfactory;プライベート最終文字列ID;プライベート最終readwritelock readwritelock = new ReentrantreadWritelock(); public MyBatisRediscache(final String ID){if(id == null){throw new IllegalargumentException( "Cache Instances required as ID"); } this.id = id; } @Override public void clear(){redisconnection 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; redisconnection connection = null; try {connection = jedisconnectionfactory.getConnection(); Redisserializer <Object> serializer = new JdkserializedRedisserializer(); result = serializer.deserialize(connection.get(serializer.serialize(key))); } catch(jedisconnectionexception e){e.printstacktrace(); }最後に{if(connection!= null){connection.close(); }} return result; } @Override public readwriteLock getReadWritelock(){return this.readwriteLock; } @Override public int getSize(){int result = 0; redisconnection connection = null; try {connection = jedisconnectionfactory.getConnection(); result = integer.valueof(connection.dbsize()。toString()); } catch(jedisconnectionexception e){e.printstacktrace(); }最後に{if(connection!= null){connection.close(); }} return result; } @Override public void putobject(object key、object value){redisconnection connection = null; try {connection = jedisconnectionfactory.getConnection(); Redisserializer <Object> serializer = new JdkserializedRedisserializer(); connection.set(serializer.serialize(key)、serializer.serialize(value)); } catch(jedisconnectionexception e){e.printstacktrace(); }最後に{if(connection!= null){connection.close(); }}} @Override public object remodobject(object key){redisconnection connection = null;オブジェクト結果= null; try {connection = jedisconnectionfactory.getConnection(); Redisserializer <Object> serializer = new JdkserializedRedisserializer(); result = connection.expire(serializer.serialize(key)、0); } catch(jedisconnectionexception e){e.printstacktrace(); }最後に{if(connection!= null){connection.close(); }} return result; } public static void setjedisconnectionFactory(jedisconnectionFactory jedisconnectionfactory){mybatisrediscache.jedisconnectionfactory = jedisconnectionfactory; }}知らせ:
ご覧のとおり、このクラスはSpring Virtual Machineが管理するクラスではありませんが、Spring Bean、つまりRedisconfigで生成されたBeanを注入する必要がある静的プロパティJedisconnectionFactoryがあります。
通常のクラスでは、Spring ContextAwareは通常、スプリングブート内省的SpringContextAwareを使用するために使用されます。
ここでは別の方法、静的注入が使用されます。この方法は、rediscacheTransferを通じて実装されます。
4。静的注射
rediscachetransfer.java
@componentPublic class rediscacheTransfer {@Autowired public void setJedisconnectionFactory(jedisconnectionFactory jedisconnectionFactory){mybatisrediscache.setjedisconnectionFactory(jedisconnectionfactory); }}RediscacheTransferがスプリングブートビーンであることがわかります。作成の開始時にコンテナを初期化すると、JedisconnectionFactory Beanは、SetJedisconnectionFactoryメソッドのパラメーター通過に注入されます。
SetjedisconnectionFactoryは、静的メソッドを呼び出すことにより、クラスMyBatiSrediscacheの静的プロパティを設定します。
これにより、Springコンテナによって管理されたJedisconnectionFactoryが静的ドメインに注入されます。
この時点で、コードは基本的に完了しており、以下はいくつかの構成です。主なものは(1)グローバルスイッチです。 (2)名前空間スコープスイッチ。 (3)モデルインスタンスシリアル化。
5。MyBatisレベル2キャッシュのグローバルスイッチ
前述のように、デフォルトのレベル2キャッシュはオンになっておらず、Trueに設定する必要があります。これは、グローバルレベル2キャッシュのスイッチです。
MyBatisグローバル構成。
<?xml version = "1.0" encoding = "utf-8"?> <!doctype構成public " - // mybatis.org//dtd config 3.0 // en" "http://mybatis.org/dtd/mybatis-3-config.dtd"キャッシュを無効にします。 - > <name = "cacheenabled" value = "true"/> </settings> </configuration>
DataSourceでのグローバル構成のロードは、このようなものです。
bean.setMapperLocations(new PathMatchingResourcePatterNresolver()。getResources( "classpath:mybatis-mapper/*。xml"));
mapper.xmlのストレージパスを指定します。 MyBatis-Mapperパスの下で、.xmlのすべての接尾辞が読み取ります。
bean.setConfiglocation(new ClassPathResource( "mybatis-config.xml"));
mybatis-config.xmlのストレージパスが指定され、リソースディレクトリに直接配置されます。
@bean(name = "moonlightsqlsessionfactory")@primary public sqlsessionfactory voonlightsqlsessionfactory( @qualifier( "moonlightdata")datasource datasource)スロー例外{sqlsessionfactorybean bean = new sqlsessionfactorybean(); Bean.SetDataSource(DataSource); bean.setMapperLocations(new PathMatchingResourcePatterNresolver()。getResources( "classpath:mybatis-mapper/*。xml")); bean.setConfiglocation(new ClassPathResource( "mybatis-config.xml")); return bean.getObject(); }6.マッパースコープネームスペースを構成します
前述のように、セカンダリキャッシュの範囲はマッパーネームスペースであるため、この構成はマッパーで記述する必要があります。
<マッパーネームスペース= "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"> <condructor> <idarg column = "id" javatype = "java.lang.integer" jdbctype = "integer" /> < column = "type" javatype = "java.lang.integer" jdbctype = "integer" /> <arg column = "group" javatype = "java.lang.string" jdbctype = "varchar" /> <arg column = "geo" javatype = "java.lang.string" jdbcher " /> < column = "createtime" javatype = "java.lang.string" jdbctype = "varchar" /> <arg column = "updatetime" javatype = "java.lang.string" jdbctype = "varchar" /> < /constructortor> < /resultmap> parametertype = "com.kangaroo.studio.moonlight.dao.model.geofencequeryparam" resultmap = "geofenceList"> select <include <include = "base_column"/> from geofence from 1 = 1 = 1 <1 <if test = "type!= null">およびtype =#{typing = "/> </> <">> < concat( '%'、#{name}、 '%')</if> <if> <if test = "group!= null"> and `concat( '%'、#{group}、 '%')</if> <if> <" starttime!= null "> and createTime> =#=#{stime} </if> </select> </mapper>知らせ:
名前空間の下のキャッシュタグは、ロードキャッシュの構成であり、キャッシュの使用は、実装したMyBatiSrediscacheによって正式に実装されます。
<cache type = "com.kangaroo.studio.moonlight.dao.cache.mybatisrediscache"/>
ここにはクエリQueryGeOfenceのみが実装されています。選択タグでこのSQLのキャッシュをオンまたはオフにすることができます。プロパティ値usecache = true/falseを使用します。
7。マッパーとモデル
キャッシュモデルの読み取りと書き込みは、シリアル化する必要があります。クラスが宣言されたときにのみ、Seriazableインターフェイスを実装する必要があります。
パブリッククラスのジオフェンスはシリアル化可能{// setter and getter省略}パブリッククラスGeofenceParamを実装しましたシリアル化可能{// setterとgetter省略}マッパーはまだ以前と同じです。 mapper.xmlを使用する場合、抽象関数を定義するだけです。
@MapperPublic Interface MoonLightMapper {List <Geofence> QueryGeOfence(GeofenceQueryParam GeofenceQueryParam);}この時点で、すべてのコードと構成が完了します。以下でテストしましょう。
8。それをテストします
このようなインターフェイス投稿は、コントローラーに実装されています。
@RequestMapping(value = "/fence/query"、method = requestmethod.post)@responsebody public responsentity> queryfence(@requestbody geofencequeryparam geofencequeryparam){try {integer pagenum = geofencequeryparam.getpagenum()!= null? integer pagesize = geofencequeryparam.getPagesize()!= null?geofencequeryparam.getPagesize():10; pagehelper.startpage(pagenum、pagesize);リスト<Geofence> list = moonlightmapper.querygeofence(geofencequeryparam); new ResponseNtity <>(new Response(resultCode.success、 "Query Geofence Success"、list)、httpstatus.ok); } catch(Exception e){logger.error( "Query Geofence Failed"、e); new ResponseNtity <>(new Response(resultCode.Exception、 "Query Geofence Failed"、null)、httpstatus.internal_server_error); }Curlを使用してリクエストを送信します
1)-H-コンテンツタイプ:アプリケーション/JSONメソッド
2)-D-次のものはJSON形式のパラメーターパッケージです
curl -h "content -type:application/json" -xpost http://。 。 。 /MOONLIGHT/FENCE/QUERY -D '{"name": "test"、 "group": "test"、 "type":1、 "starttime": "2017-12-06 00:00:00"、 "endtime": "3回リクエストされたログは、次のように印刷されます
ご覧のとおり、SQLテンプレートクエリが初めて実行され、キャッシュがヒットしました。
テスト環境では、データが比較的少ないため、クエリ速度のキャッシュ最適化は明らかではありません。ここではあまり説明しません。