Статьи

Учебник по Spring Data Solr: добавление пользовательских методов во все репозитории

Если мы используем Spring Data Solr в реальном программном проекте, есть вероятность, что рано или поздно мы столкнемся с требованием, согласно которому наше приложение должно иметь возможность взаимодействовать как с локальным сервером Solr, так и с SolrCloud . На данный момент выполнение этого требования означает, что мы должны добавить пользовательские методы во все репозитории Spring Data Solr. Этот блог описывает, как это делается.

В качестве примера, мы изменим пример приложения предыдущей части моего учебника по Spring Data Solr . Во время этой записи в блоге мы изменим реализацию этого приложения в хранилище таким образом, чтобы все его методы добавлялись во все хранилища.

Примечание. Это, конечно, немного наивный пример, поскольку пользовательский интерфейс и его реализация связаны с классом TodoDocument .

Мы можем добавить пользовательские методы во все репозитории, выполнив следующие действия:

  1. Получить необходимые зависимости с Maven
  2. Создайте интерфейс, который объявляет пользовательские методы.
  3. Реализуйте созданный интерфейс.
  4. Создайте пользовательский репозиторий фабричного компонента.
  5. Сконфигурируйте Spring Data Solr для использования пользовательского фабричного компонента хранилища.

Примечание. Эти сообщения в блоге предоставляют дополнительную информацию, которая помогает нам понять концепции, описанные в этом сообщении:

Хватит болтовни. Давайте начнем.

Получение необходимых зависимостей с Maven

Пример приложения этого поста блога использует снимок сборки Spring Data Solr, поскольку он обеспечивает лучшую поддержку для реализации пользовательских компонентов фабрики репозитория. Мы можем получить необходимые зависимости, внеся следующие изменения в наш файл POM:

  1. Добавьте репозиторий моментальных снимков Spring в раздел репозитории файла pom.xml .
  2. Измените версию зависимости Spring Data Solr.

Эти шаги описаны более подробно в следующих подразделах.

Использование репозитория моментальных снимков Spring

Мы можем использовать репозиторий Spring snapshot Maven, добавив следующую конфигурацию репозитория в наш файл POM:

1
2
3
4
5
6
7
<repositories>
    <repository>
        <id>spring-snapshots</id>
        <name>Spring Snapshot Maven Repository</name>
    </repository>
</repositories>

Обновление Spring Data Solr версии

Мы можем использовать снимок сборки Spring Data Solr, добавив следующее объявление зависимости в файл pom.xml .

1
2
3
4
5
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-solr</artifactId>
    <version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>

Создание пользовательского интерфейса репозитория

Мы можем создать собственный интерфейс для наших репозиториев, выполнив следующие действия:

  1. Создайте интерфейс с именем CustomBaseRepository, который имеет два параметра типа: тип документа ( T ) и идентификатор документа ( ID ).
  2. Убедитесь, что интерфейс CustomBaseRepository расширяет интерфейс SolrCrudRepository .
  3. Аннотируйте интерфейс с помощью аннотации @NoRepositoryBean . Это гарантирует, что Spring Data Solr не будет пытаться создать реализацию для нашего интерфейса.
  4. Добавьте объявления методов count () и update () в интерфейс CustomBaseRepository .

Исходный код интерфейса CustomBaseRepository выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.solr.repository.SolrCrudRepository;
 
import java.io.Serializable;
 
@NoRepositoryBean
public interface CustomBaseRepository<T, ID extends Serializable> extends SolrCrudRepository<T, ID> {
 
    public long count(String searchTerm);
 
    public void update(Todo todoEntry);
}

Наш следующий шаг — реализовать созданный интерфейс. Давайте выясним, как это делается.

Реализация пользовательского интерфейса репозитория

Мы можем реализовать пользовательский репозиторий, выполнив следующие действия:

  1. Создайте класс с именем CustomBaseRepositoryImpl . Этот класс имеет два параметра типа: тип документа ( T ) и тип идентификатора документа ( ID ).
  2. Убедитесь, что созданный класс расширяет класс SimpleSolrRepository и реализует интерфейс CustomBaseRepository .
  3. Создайте конструктор, который принимает объект SolrOperations и тип класса документа в качестве аргументов конструктора. Реализация этого конструктора просто вызывает конструктор суперкласса.
  4. Реализуйте метод update () . Поскольку реализация этого метода была описана в этом сообщении в блоге , я не буду вдаваться в подробности здесь.
  5. Реализуйте метод count () . Опять же, я не буду вдаваться в подробности, потому что реализация этого метода была описана ранее .

Исходный код класса CustomBaseRepositoryImpl выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import org.springframework.data.solr.core.SolrOperations;
import org.springframework.data.solr.core.query.Criteria;
import org.springframework.data.solr.core.query.PartialUpdate;
import org.springframework.data.solr.core.query.SimpleQuery;
import org.springframework.data.solr.repository.support.SimpleSolrRepository;
 
import java.io.Serializable;
 
public class CustomBaseRepositoryImpl<T, ID extends Serializable> extends SimpleSolrRepository<T, ID> implements CustomBaseRepository<T, ID> {
 
    public CustomBaseRepositoryImpl(SolrOperations solrOperations, Class<T> entityClass) {
        super(solrOperations, entityClass);
    }
 
    @Override
    public long count(String searchTerm) {
        String[] words = searchTerm.split(" ");
        Criteria conditions = createSearchConditions(words);
        SimpleQuery countQuery = new SimpleQuery(conditions);
 
        return getSolrOperations().count(countQuery);
    }
 
    private Criteria createSearchConditions(String[] words) {
        Criteria conditions = null;
 
        for (String word: words) {
            if (conditions == null) {
                conditions = new Criteria("title").contains(word)
                        .or(new Criteria("description").contains(word));
            }
            else {
                conditions = conditions.or(new Criteria("title").contains(word))
                        .or(new Criteria("description").contains(word));
            }
        }
 
        return conditions;
    }
 
    @Override
    public void update(Todo todoEntry) {
        PartialUpdate update = new PartialUpdate("id", todoEntry.getId().toString());
 
        update.add("description", todoEntry.getDescription());
        update.add("title", todoEntry.getTitle());
 
        getSolrOperations().saveBean(update);
        getSolrOperations().commit();
    }
}

Давайте переместимся и узнаем, как мы можем создать пользовательский компонент фабрики репозитория.

Создание пользовательского репозитория Factory Bean

Компонент фабрики репозитория является компонентом, отвечающим за создание реализаций интерфейсов репозитория. Поскольку мы хотим использовать класс CustomBaseRepositoryImpl в качестве реализации наших репозиториев Spring Data Solr, мы должны создать пользовательский компонент фабрики репозитория.

Мы можем создать новый bean-компонент фабрики репозитория, выполнив следующие действия:

  1. Создайте класс с именем CustomSolrRepositoryFactoryBean, который расширяет класс SolrRepositoryFactoryBean .
  2. Добавьте закрытый класс CustomSolrRepositoryFactory в класс бина CustomSolrRepositoryFactory . Этот класс расширяет класс SolrRepositoryFactory и имеет два параметра типа: тип документа ( T ) и тип идентификатора документа ( ID ).
  3. Переопределите метод doCreateRepositoryFactory () класса SolrRepositoryFactoryBean . Реализация этого метода возвращает новый объект CustomSolrRepositoryFactory .

Давайте подробнее рассмотрим реализацию класса CustomSolrRepositoryFactory . Мы можем реализовать это, выполнив следующие действия:

  1. Добавьте поле SolrOperations в класс CustomSolrRepositoryFactory .
  2. Добавьте конструктор в класс CustomSolrRepositoryFactory . Этот класс принимает используемый объект SolrOperations в качестве аргумента конструктора. Его реализация просто вызовет конструктор суперкласса и установит полученный объект SolrOperations в поле, которое мы создали в первом шаге.
  3. Переопределите метод getTargetRepository () класса SolrRepositoryFactory и верните новый объект CustomBaseRepositoryImpl .
  4. Переопределите метод getRepositoryBaseClass () класса SolrRepositoryFactory и верните тип нашего пользовательского интерфейса.

Вот и все. Исходный код нашего пользовательского компонента фабрики хранилища выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import org.springframework.data.solr.core.SolrOperations;
import org.springframework.data.solr.repository.support.SolrRepositoryFactory;
import org.springframework.data.solr.repository.support.SolrRepositoryFactoryBean;
 
import java.io.Serializable;
 
public class CustomSolrRepositoryFactoryBean extends SolrRepositoryFactoryBean {
 
    @Override
    protected RepositoryFactorySupport doCreateRepositoryFactory() {
        return new CustomSolrRepositoryFactory(getSolrOperations());
    }
 
    private static class CustomSolrRepositoryFactory<T, ID extends Serializable> extends SolrRepositoryFactory {
 
        private final SolrOperations solrOperations;
 
        public CustomSolrRepositoryFactory(SolrOperations solrOperations) {
            super(solrOperations);
            this.solrOperations = solrOperations;
        }
        
        @Override
        protected Object getTargetRepository(RepositoryMetadata metadata) {
            return new CustomBaseRepositoryImpl<T, ID>(solrOperations, (Class<T>) metadata.getDomainType());
        }
 
        @Override
        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return CustomBaseRepository.class;
        }
    }
}

Следующим шагом будет настройка Spring Data Solr для использования фабричного компонента репозитория, который мы только что создали. Давайте начнем.

Настройка Spring Data Solr

Нашим последним шагом является настройка Spring Data Solr для использования нового фабричного компонента репозитория, который мы создали на предыдущем шаге. Мы можем сделать это, используя либо класс конфигурации Java, либо файл конфигурации XML. Оба эти варианта описаны в следующих подразделах.

Примечание . Различные файлы конфигурации, представленные в следующих подразделах, для ясности упрощены. На самом деле наше примерное приложение имеет различную конфигурацию для среды разработки и производства .

Конфигурация Java

Если мы используем конфигурацию Java, мы можем настроить Spring Data Solr для использования пользовательского фабричного компонента хранилища с помощью атрибута repositoryFactoryBeanClass аннотации @EnableJpaRepositories . Исходный код класса конфигурации выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
import org.springframework.context.annotation.Configuration;
import org.springframework.data.solr.repository.config.EnableSolrRepositories;
 
@Configuration
@EnableSolrRepositories(
        basePackages = "net.petrikainulainen.spring.datasolr.todo.repository.solr",
        repositoryFactoryBeanClass = CustomSolrRepositoryFactoryBean.class
)
public class SolrContext {
 
    //Configuration is omitted.
}

Конфигурация XML

Когда мы используем конфигурацию XML, мы можем настроить Spring Data Solr на использование собственного фабричного компонента хранилища, используя атрибут factory-class элемента пространства имен хранилища . Файл конфигурации XML нашего контекста приложения выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>
 
    <!-- Enable Solr repositories and configure repository base package -->
    <solr:repositories base-package="net.petrikainulainen.spring.datasolr.todo.repository.solr"
                      factory-class="net.petrikainulainen.spring.datasolr.todo.repository.solr.CustomSolrRepositoryFactoryBean"/>
 
    <!-- The configuration is omitted. -->
</Beans>

Резюме

Теперь мы создали два пользовательских метода, которые добавляются во все репозитории нашего примера приложения. Конечно, как мы узнали ранее, этот пример не имеет никакого смысла, потому что наш пользовательский интерфейс репозитория и его реализация привязаны к классу TodoDocument .

Этот урок научил нас двум вещам:

  • Мы можем использовать аннотацию @NoRepositoryBean, чтобы сообщить Spring Data Solr, что ему не следует создавать реализацию для интерфейса, аннотированного аннотацией @NoRepositoryBean .
  • Мы можем сконфигурировать пользовательский фабричный bean-компонент репозитория, используя атрибут repositoryFactoryBeanClass аннотации @EnableSolrRepositories или атрибут factory-class элемента пространства имен репозиториев .

Как всегда, пример приложения этого блога доступен на Github .