Статьи

Учебник по Spring Data Solr: CRUD (почти)

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

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

  1. Создайте класс документа, который содержит информацию, хранящуюся в индексе Solr.
  2. Создайте интерфейс репозитория для нашего репозитория Spring Data Solr.
  3. Создайте сервис, который использует созданный репозиторий.
  4. Воспользуйтесь созданным сервисом.

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

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

Создание класса документа

Первым шагом является создание класса документа, который содержит информацию, добавленную в индекс Solr. Класс документа — это просто POJO, который реализуется по следующим правилам:

  • Аннотация @Field используется для создания связи между полями POJO и полями документа Solr.
  • Если имя поля компонента не совпадает с именем поля документа, имя поля документа должно быть указано в качестве значения аннотации @Field .
  • Аннотация @Field может быть применена к методу поля или метода установки.
  • Spring Data Solr по умолчанию предполагает, что именем поля id документа является ‘id’. Мы можем переопределить этот параметр, пометив поле id аннотацией @Id .
  • Spring Data Solr (версия 1.0.0.RC1) требует, чтобы тип идентификатора документа был String .

Больше информации :

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

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

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

  1. Создайте класс с именем TodoDocument .
  2. Добавьте поле id в класс TodoDocument и аннотируйте поле аннотацией @Field . Аннотируйте поле с помощью аннотации @Id (это не требуется, так как имя поля id — ‘id’, но я хотел продемонстрировать его использование здесь).
  3. Добавьте поле описания в класс TodoDocument и аннотируйте это поле аннотацией @Field .
  4. Добавьте поле заголовка в TodoDocument и аннотируйте это поле аннотацией @Field .
  5. Создайте методы получения для полей класса TodoDocument .
  6. Создайте статический внутренний класс, который используется для создания новых объектов TodoDocument .
  7. Добавьте статический метод getBuilder () в класс TodoDocument . Реализация этого метода возвращает новый объект TodoDocument.Builder .

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

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
import org.apache.solr.client.solrj.beans.Field;
import org.springframework.data.annotation.Id;
 
public class TodoDocument {
 
    @Id
    @Field
    private String id;
 
    @Field
    private String description;
 
    @Field
    private String title;
 
    public TodoDocument() {
 
    }
 
    public static Builder getBuilder(Long id, String title) {
        return new Builder(id, title);
    }
 
    //Getters are omitted
 
    public static class Builder {
        private TodoDocument build;
 
        public Builder(Long id, String title) {
            build = new TodoDocument();
            build.id = id.toString();
            build.title = title;
        }
 
        public Builder description(String description) {
            build.description = description;
            return this;
        }
 
        public TodoDocument build() {
            return build;
        }
    }
}

Создание интерфейса репозитория

Базовым интерфейсом репозиториев Spring Data Solr является интерфейс SolrCrudRepository <T, ID>, и каждый интерфейс репозитория должен расширять этот интерфейс.

Когда мы расширяем интерфейс SolrCrudRepository <T, ID> , мы должны предоставить два параметра типа, которые описаны ниже:

  • Параметр T type означает тип нашего класса документов.
  • Параметр типа ID означает тип идентификатора документа. Spring Data Solr (версия 1.0.0.RC1) требует, чтобы идентификатор документа был String .

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

  1. Создайте интерфейс под названием TodoDocumentRepository .
  2. Расширьте интерфейс SolrCrudRepository и укажите тип нашего класса документа и его идентификатор в качестве параметров типа.

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

1
2
3
4
import org.springframework.data.solr.repository.SolrCrudRepository;
 
public interface TodoDocumentRepository extends SolrCrudRepository<TodoDocument, String> {
}

Создание сервиса

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

  1. Создать сервисный интерфейс.
  2. Реализуйте созданный интерфейс.

Эти шаги описаны более подробно ниже.

Создание сервисного интерфейса

Наш сервисный интерфейс объявляет два метода, которые описаны ниже:

  • Метод void addToIndex (Todo todoEntry) добавляет запись индекса в индекс.
  • Метод void deleteFromIndex (Long id) удаляет запись todo из индекса.

Примечание. Мы можем использовать метод addToIndex () для добавления новых записей задач в индекс Solr и обновления информации о существующих записях задач. Если существующий документ имеет тот же идентификатор, что и новый, старый документ удаляется, а информация о новом документе сохраняется в индексе Solr (см. SchemaXML @ Solr Wiki для получения дополнительной информации).

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

1
2
3
4
5
6
public interface TodoIndexService {
 
    public void addToIndex(Todo todoEntry);
 
    public void deleteFromIndex(Long id);
}

Реализация созданного интерфейса

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

  1. Создайте каркасную реализацию нашего класса обслуживания.
  2. Реализуйте метод, используемый для добавления документов в индекс Solr.
  3. Реализуйте метод, используемый для удаления документов из индекса Solr.

Эти шаги описаны более подробно ниже.

Создание скелетной реализации класса обслуживания

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

  1. Создайте класс с именем RepositoryTodoIndexService и аннотируйте этот класс аннотацией @Service . Эта аннотация помечает этот класс как службу и гарантирует, что класс будет обнаружен во время сканирования пути к классу.
  2. Добавьте поле TodoDocumentRepository в класс RepositoryTodoIndexService и аннотируйте это поле аннотацией @Resource . Эта аннотация указывает контейнеру Spring IoC ввести фактическую реализацию репозитория в поле репозитория службы.

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

01
02
03
04
05
06
07
08
09
10
11
12
13
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;
 
    //Add methods here
}

Добавление документов в индекс Solr

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

  1. Добавьте метод addToIndex () в класс RepositoryTodoIndexService и аннотируйте этот метод аннотацией @Transactional . Это гарантирует, что наш репозиторий Spring Data Solr будет участвовать в управляемых Spring транзакциях .
  2. Создайте новый объект TodoDocument , используя шаблон построителя. Установите идентификатор , название и описание созданного документа.
  3. Добавьте документ в индекс Solr, вызвав метод save () интерфейса TodoDocumentRepository .

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

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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import javax.annotation.Resource;
 
@Service
public class RepositoryTodoIndexService implements TodoIndexService {
 
    @Resource
    private TodoDocumentRepository repository;
 
    @Transactional
    @Override
    public void addToIndex(Todo todoEntry) {
        TodoDocument document = TodoDocument.getBuilder(todoEntry.getId(), todoEntry.getTitle())
                .description(todoEntry.getDescription())
                .build();
        
        repository.save(document);
    }
 
    //Add deleteFromIndex() method here
}

Удаление документов из индекса Solr

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

  1. Добавьте метод deleteFromIndex () в класс RepositoryTodoDocumentService и аннотируйте этот метод аннотацией @Transactional . Это гарантирует, что наш репозиторий Spring Data Solr будет участвовать в управляемых Spring транзакциях .
  2. Удалите документ из индекса Solr, вызвав метод delete () интерфейса TodoDocumentRepository .

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

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;
 
    //Add addToIndex() method here
 
    @Transactional
    @Override
    public void deleteFromIndex(Long id) {
        repository.delete(id.toString());
    }
}

Использование созданного сервиса

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

  1. Добавьте поле TodoIndexService в класс RepositoryTodoService и аннотируйте это поле аннотацией @Resource . Эта аннотация указывает контейнеру IoC Spring на добавление созданного объекта RepositoryTodoIndexService в поле службы indexService .
  2. Вызовите метод addToIndex () интерфейса TodoIndexService в методе add () класса RepositoryTodoService .
  3. Вызовите метод deleteFromIndex () интерфейса TodoIndexService в методе deleteById () класса RepositoryTodoService .
  4. Вызовите метод addToIndex () интерфейса TodoIndexService в методе update () класса RepositoryTodoService .

Исходный код 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import javax.annotation.Resource;
import java.util.List;
 
@Service
public class RepositoryTodoService implements TodoService {
 
    @Resource
    private TodoIndexService indexService;
 
    @Resource
    private TodoRepository repository;
 
    @PreAuthorize("hasPermission('Todo', 'add')")
    @Transactional
    @Override
    public Todo add(TodoDTO added) {
        Todo model = Todo.getBuilder(added.getTitle())
                .description(added.getDescription())
                .build();
 
        Todo persisted = repository.save(model);
        indexService.addToIndex(persisted);
 
        return persisted;
    }
 
    @PreAuthorize("hasPermission('Todo', 'delete')")
    @Transactional(rollbackFor = {TodoNotFoundException.class})
    @Override
    public Todo deleteById(Long id) throws TodoNotFoundException {
        Todo deleted = findById(id);
 
        repository.delete(deleted);
        indexService.deleteFromIndex(id);
 
        return deleted;
    }
 
    @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.addToIndex(model);
 
        return model;
    }
}

Резюме

Мы успешно создали приложение, которое добавляет документы в индекс Solr и удаляет из него документы. Эта запись в блоге научила нас следующим вещам:

  • Мы узнали, как мы можем создавать классы документов.
  • Мы узнали, что можем создавать репозитории Spring Data Solr, расширяя интерфейс SolrCrudRepository .
  • Мы узнали, что Spring Data Solr по умолчанию предполагает, что именем поля id документа является ‘id’. Однако мы можем переопределить этот параметр, добавив в поле id аннотацию @Id .
  • Мы узнали, что в настоящий момент Spring Data Solr (версия 1.0.0.RC1) ожидает, что идентификатором документа является String .
  • Мы узнали, как мы можем добавлять документы в индекс Solr и удалять документы из него.
  • Мы узнали, что репозитории Spring Data Solr могут участвовать в транзакциях, управляемых Spring.

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

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