Статьи

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

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

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

Что такое частичное обновление?

Функция частичного обновления была введена в Solr 4.0 и дает нам возможность выбирать поля, которые будут обновлены. Это может быть очень полезно, если индексирование содержимого всего документа происходит медленно.

Однако функция частичного обновления имеет свои ограничения. Если мы хотим использовать функцию частичного обновления, мы должны сохранить все поля документа, что увеличивает размер индекса Solr. Причина этого заключается в том, что невозможно выполнить частичное обновление индекса Lucene. Lucene всегда удаляет старый документ перед индексацией нового. Это означает, что если поля, которые не были обновлены, не сохраняются, значения этих полей теряются при частичном обновлении документа.

Наша задача — решить, какой из них важнее для нас: скорость или размер индекса.

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

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

Добавление пользовательских методов в один репозиторий

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

  1. Создайте пользовательский интерфейс, который объявляет пользовательские методы.
  2. Реализуйте пользовательский интерфейс.
  3. Измените интерфейс репозитория, чтобы расширить пользовательский интерфейс.

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

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

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

  1. Создайте интерфейс с именем PartialUpdateRepository .
  2. Объявите пользовательские методы.

Поскольку мы должны объявить только один пользовательский метод, который используется для обновления информации записи todo, исходный код интерфейса PartialUpdateRepository выглядит следующим образом:

1
2
3
4
public interface PartialUpdateRepository {
 
    public void update(Todo todoEntry);
}

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

Во-вторых, мы должны реализовать интерфейс PartialUpdateRepository . Инфраструктура хранилища пытается автоматически определить классы, которые реализуют пользовательские интерфейсы хранилища, используя следующие правила:

  • Реализация пользовательского интерфейса репозитория должна быть найдена из того же пакета, что и пользовательский интерфейс.
  • Имя класса, который реализует пользовательский интерфейс репозитория, должно быть создано с помощью следующей формулы: [Имя фактического интерфейса репозитория] [Постфикс реализации репозитория] .

Значением по умолчанию для постфикса реализации репозитория является «Impl». Мы можем перезаписать значение по умолчанию одним из следующих способов:

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

  1. Создайте класс с именем TodoDocumentRepositoryImpl .
  2. Аннотируйте класс с помощью аннотации @Repository .
  3. Добавьте поле SolrTemplate в класс и аннотируйте это поле аннотацией @Resource .
  4. Реализуйте метод update () .

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

  1. Создайте новый объект PartialUpdate . Установите имя поля id документа и его значение в качестве аргументов конструктора.
  2. Установите имена и значения обновленных полей для созданного объекта.
  3. Выполните частичное обновление, вызвав метод saveBean () класса SolrTemplate .
  4. Зафиксируйте изменения, вызвав метод commit () класса SolrTemplate .

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.core.query.PartialUpdate;
import org.springframework.stereotype.Repository;
 
import javax.annotation.Resource;
 
@Repository
public class TodoDocumentRepositoryImpl implements PartialUpdateRepository {
 
    @Resource
    private SolrTemplate solrTemplate;
 
    @Override
    public void update(Todo todoEntry) {
        PartialUpdate update = new PartialUpdate("id", todoEntry.getId().toString());
 
        update.add("description", todoEntry.getDescription());
        update.add("title", todoEntry.getTitle());
 
        solrTemplate.saveBean(update);
        solrTemplate.commit();
    }
}

Модификация интерфейса репозитория

Мы можем сделать пользовательский метод update () видимым для пользователей нашего репозитория, расширив интерфейс PartialUpdateRepository . Исходный код интерфейса TodoDocumentRepository выглядит следующим образом:

1
2
3
4
5
6
import org.springframework.data.solr.repository.SolrCrudRepository;
 
public interface TodoDocumentRepository extends PartialUpdateRepository, SolrCrudRepository<TodoDocument, String> {
 
    //Query methods are omitted.
}

Давайте продолжим и узнаем, как мы можем использовать наш новый метод хранилища.

Использование пользовательского метода

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

  1. Добавьте метод update () в интерфейс TodoIndexService.
  2. Реализуйте метод update () .
  3. Измените метод update () класса RepositoryTodoService, чтобы использовать новый метод.

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

Добавление нового метода в интерфейс TodoIndexService

Как мы помним, интерфейс TodoIndexRepository объявляет методы, которые используются для добавления информации в индекс Solr, поиска информации из него и удаления документов из индекса.

Мы должны добавить новый метод в этот интерфейс. Этот метод называется update (), и он принимает обновленный объект Todo в качестве параметра метода. Исходный код интерфейса TodoIndexRepository выглядит следующим образом:

1
2
3
4
5
6
public interface TodoIndexService {
 
    //Other methods are omitted.
 
    public void update(Todo todoEntry);
}

Реализация добавленного метода

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

  1. Добавьте метод update () в класс RepositoryIndexService и аннотируйте метод аннотацией @Transactional . Это гарантирует, что наш репозиторий Spring Data Solr будет участвовать в управляемых Spring транзакциях .
  2. Вызовите метод репозитория update () и передайте обновленный объект Todo в качестве параметра метода.

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import javax.annotation.Resource;
 
@Service
public class RepositoryTodoIndexService implements TodoIndexService {
 
    @Resource
    private TodoDocumentRepository repository;
 
    //Other fields and methods are omitted.
 
    @Transactional
    @Override
    public void update(Todo todoEntry) {
        repository.update(todoEntry);
    }
}

Изменение класса RepositoryTodoService

Нашим последним шагом является изменение метода update () класса RepositoryTodoService для использования нового метода update (), который объявлен в интерфейсе TodoIndexService . Соответствующие части класса RepositoryTodoService выглядят следующим образом:

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
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import javax.annotation.Resource;
 
@Service
public class RepositoryTodoService implements TodoService {
 
    @Resource
    private TodoIndexService indexService;
 
    @Resource
    private TodoRepository repository;
 
    //Other methods are omitted.
 
    @PreAuthorize("hasPermission('Todo', 'update')")
    @Transactional(rollbackFor = {TodoNotFoundException.class})
    @Override
    public Todo update(TodoDTO updated) throws TodoNotFoundException {
        Todo model = findById(updated.getId());
 
        model.update(updated.getDescription(), updated.getTitle());
 
        indexService.update(model);
 
        return model;
    }
}

Резюме

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

  • Мы знаем, как мы можем добавить пользовательские методы в один репозиторий Spring Data Solr.
  • Мы знаем, что можем использовать частичное обновление, только если все поля нашего документа сохранены (значение хранимого атрибута равно true).

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

PS Пример приложения этой записи в блоге доступен на Github .