Предисловие
Что такое кэш Mybatis уровня 2?
Вторичный кэш делится несколькими SQLSessions, а его объем является тем же пространством имен на карте.
То есть в разных SQLSessions, в одном и том же пространстве имен, одном и том же операторе SQL, а параметры в шаблоне SQL также одинаковы, и кэш будет достигнут.
После первого выполнения данные, запрошенные в базе данных, будут записаны в кэш, а данные будут извлечены из кэша больше не будут запрашивать из базы данных, тем самым повышая эффективность запроса.
Mybatis не включает вторичный кэш по умолчанию, и необходимо включить вторичный кэш в глобальной конфигурации (mybatis-config.xml).
В этой статье описывается метод использования Redis в качестве кэша для интеграции с Springboot и Mybatis.
1. Зависимость точки
Используйте интеграционный пакет Springboot Redis, чтобы облегчить доступ к Redis. Jedis используется на клиенте Redis.
Кроме того, чтение и написание кВ -кэш будет сериализовано, поэтому вводится пакет сериализации.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.8.0</version> </dependency> <dependency> <groupId> com.alibaba </GroupId> <ratifactId> FastJson </artifactId> <sersion> 1.2.19 </version> </depervice>
После того, как зависимость завершена, следующим шагом является настройка клиента Redis.
2. Бобы, используемые Redis Access
Добавьте конфигурацию, настройте JedisconnectionFactory Bean и оставьте его для дальнейшего использования.
Вообще говоря, также будет создан боб Redistemplate, но он не используется в следующем сценарии.
@Configurationpublic class redisconfig {@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 (name = "jedisconnectionFactory") 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, следующие
#sedisspring.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 был настроен, и мы начинаем настраивать Redis в качестве кэша для Mybatis.
3. Mybatis Cache
Этот шаг - самый важный шаг. Метод реализации заключается в реализации интерфейса org.apache.ibatis.cache.cache из Mybatis.
Этот интерфейс проектирует кеш записи, кэш считывает, уничтожает кэш и управление доступа к блокировке чтения и записи.
Класс, который мы реализуем для реализации интерфейса кэша, - это mybatisrediscache.
Mybatisrediscache.java
открытый класс mybatisrediscache реализует кэш {private static jedisconnectionfactory jedisconnectionFactory; Частный финальный идентификатор строки; Private Final ReadWritelock ReadWritelock = new ReenterTreadWriteLock (); public mybatisrediscache (Final String Id) {if (id == null) {бросить новый allosalargumentException ("экземпляры кэша требуют идентификатора"); } 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 result = null; Redisconnection Connection = null; try {connection = jedisconnectionFactory.getConnection (); Redisserializer <object> serializer = new jdkserializationredisserializer (); 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 (ключ объекта, значение объекта) {redisconnection connection = null; try {connection = jedisconnectionFactory.getConnection (); Redisserializer <object> serializer = new jdkserializationredisserializer (); connection.set (serializer.serialize (key), serializer.serialize (value)); } catch (jedisconnectionException e) {e.printstackTrace (); } наконец {if (connection! = null) {connection.close (); }}} @Override public object removeObject (ключ объекта) {redisconnection connection = null; Объект результат = null; try {connection = jedisconnectionFactory.getConnection (); Redisserializer <object> serializer = new jdkserializationredisserializer (); 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, но существует статическое свойство JedisconnectionFactory, которое требует введения пружинного боба, то есть бобов, генерируемого в Redisconfig.
В нормальном классе Spring Contextaware обычно используется для использования интроспективного Springboot Springcontextaware.
Другой метод используется здесь, статическая инъекция. Этот метод реализован через Rediscachetransfer.
4. Статическая инъекция
Rediscachetransfer.java
@Componentpublic class resiscachetransfer {@autowired public void setjedisconnectionFactory (jedisconnectionFactory jedisconnectionFactory) {mybatisrediscache.setjedisconnectionFactory (jedisconnectionFactory); }}Вы можете видеть, что rediscachetransfer - это боб Springboot. При инициализации контейнера в начале создания боб JedisconnectionFactory будет вводить в параметр прохождения метода SetJedisconnectionFactory.
SetJedisconnectionFactory устанавливает статическое свойство класса MyBatisrediscache, вызывая статический метод.
Это вводит JedisconnectionFactory, управляемый контейнером пружины в статический домен.
На этом этапе код в основном был завершен, и ниже приведены некоторые конфигурации. Основными являются (1) глобальный переключатель; (2) коммутатор пространства пространства имен; (3) Сериализация экземпляра модели.
5. Глобальный переключатель кэша 2 уровня Mybatis.
Как упоминалось ранее, кэш уровня 2 по умолчанию не включен и должен быть установлен на True. Это переключатель для кэша глобального уровня 2.
Глобальная конфигурация Mybatis.
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration> <!-- Global Parameters--> <settings> <!-- Make the global mapper enable или отключить кеш. -> <Настройка name = "cacheenabled" value = "true"/> </settings> </configuration>
Загрузка глобальных конфигураций в дату данных может быть такой.
bean.setmapperlocations (новый PathmatchingResourcepatternResolver (). getResources ("ClassPath: mybatis-mapper/*. xml"));
Указывает путь хранения Mapper.xml. Под пути Mybatis-Mapper все суффиксы с .xml будут прочитаны.
bean.setConfiglocation (новый ClassPathresource ("mybatis-config.xml"));
Путь хранения mybatis-config.xml указан и размещен непосредственно в каталоге ресурсов.
@Bean (name = "moonlightsqlSessionFactory") @primary public sqlSessionFactory MoonlightSqlSessionFactory (@qualifier ("MoonlightData") DataSource DataSource) вызывает исключение {sqlSessionFactorybean bean = new sqlSessionFactorybean ();); bean.setDataSource (DataSource); bean.setmapperlocations (новый PathmatchingResourcepatternResolver (). getResources ("ClassPath: mybatis-mapper/*. xml")); bean.setConfiglocation (новый ClassPathresource ("mybatis-config.xml")); return bean.getObject (); }6. Настройте пространство имен имен Mapper
Как упоминалось ранее, объем вторичного кеша является пространством имен Mapper, поэтому эта конфигурация должна быть записана в Mapper.
<mapper namespace = "com.kangaroo.studio.moonlight.dao.mapper.moonlightmapper"> <cache type = "com.kangaroo.studio.moonlight.dao.cache.mybatisrediscache"/> <refulmap id = "geofencelist" type = "com.kangaroo.studio.moonlight.dao.model.geofence"> <stonfuctor> <idarg column = "id" javatype = "java.lang.integer" jdbctype = "integer" /> <arge column " /javatype =" java.lang.string " /> <arge column =" javatype = " Column = "type" javatype = "java.lang.integer" jdbctype = "integer" /> <arg column = "group" javatype = "java.lang.string" jdbctype = "varchar" /> <arg column = "geo" javatype = "java.lang.lang.string" jdbtpe " /javatype =" java.lang.lang.lang column = "createTime" javatype = "java.lang.string" jdbctype = "varchar" /> <arg column = "updateTime" javatype = "java.lang.string" jdbctype = "varchar" /> < /contructor> < /resultmap> <select id = "querygence" /> < /contructor> < /recultmap> <select Id = " ParameterType = "com.kangaroo.studio.moonlight.dao.model.geofencequeryparam" resultmap = "geoFenceList"> SELECT <Cult RefID = "BASE_COLUMN"/> From Geofence, где 1 = 1 <if test = "type! = null" и type = #{typence} </if> <if test = "= null" и null "и type = #{if> <if test =" и "null" и null "и type = #{if test =" и "null" и null "и type = # concat ('%', #{name}, '%') </if> <if test = "group! = null"> и `group` like concat ('%', #{group}, '%') </if> <if test =" starttime! = null "> и CreateTime> = #{startTime} </if test =" endtime! = nullime> и nulletime> и endteTime} </if test = "nulltime> и nullime> и nulletime> и nulletime> и endtime} </if test = endtime! </if> </select> </mapper>Уведомление:
Кэш -тег в пространстве имен - это конфигурация загрузки кэша, а использование кэша официально реализовано MyBatisrediscache, которую мы только что реализовали.
<cache type = "com.kangaroo.studio.moonlight.dao.cache.mybatisrediscache"/>
Здесь реализовано только запрос запроса. Вы можете включить или выключить кэш этого SQL в теге Select. Используйте значение свойства usecache = true/false.
7. Mapper и модель
Читать и писать модель кэша должна быть сериализована: ей необходимо реализовать интерфейс Seriazible, только когда класс объявлен.
Открытый класс Геофенса реализует Serializable {// Setter и Getter опущено} Открытый класс GeofenceParam реализует serializable {// setter и getter опущено}Mapper по -прежнему такой же, как и раньше. При использовании mapper.xml вам нужно только определить абстрактные функции.
@Mapperpublic interface moonlightmapper {list <geofence> QuerygeOfence (GeofenceQueryparam GeofenceQueryparam);}На этом этапе весь код и конфигурация завершены, давайте проверим его ниже.
8. Проверьте это
Такая интерфейсная публикация реализована в контроллере.
@Requestmapping (value = "/warg/Query", method = requestmethod.post) @responsebody public responsementity <sonsecting> QueryFence (@Requestbody geofencequeryparam) {try {Integer pagenum = geofencequeryparam.getpagenum ()! = null? GeofenceQueryparam.getPagenum (): 1; Integer pagesize = geofencequeryparam.getPagesize ()! = Null? GeofenceQueryparam.getPagesize (): 10; PageHelper.StartPage (Pagenum, PageSize); Список <Геофенса> List = MoonlightMapper.QuerygeOfence (GeofenceQueryparam); вернуть новую реакцию <> (новый ответ (resultcode.success, «Query Geofence Success», List), httpstatus.ok); } catch (Exception e) {logger.error ("Query Geofence не удалось", E); вернуть новую реакцию <> (новый ответ (resultCode.exception, "Query Geofence не удастся", 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", "Законное время": "2017-12-06 16:00:00", "Pagenum": 1, "PageSize": 8Запрашивается три раза, журнал печатается следующим образом
Как видите, только первый раз, когда был выполнен запрос шаблона SQL, и кэш был поражен.
В нашей тестовой среде, из -за относительно небольшого количества данных, оптимизация кэша скорости запроса не очевидна. Я не буду много объяснить здесь.