Есть ли способ создать универсальный интерфейс, который расширяет MongoRepository? - PullRequest
0 голосов
/ 18 октября 2018

Учитывая следующий код, есть ли способ создать универсальный интерфейс репозитория, который можно использовать для всех объектов?

У меня такая ситуация:

Model.java

public abstract class Model {
    @Id
    protected String id;
    // getter and setter
}

Controller.java

public abstract class Controller<T extends Model> {

    @Autowired
    protected Repository<T> repository;
    // ...

}

Repository.java

public interface Repository<T> extends MongoRepository<T, String> {
}

Когда я создаюPerson сущность и PersonController

Person.java

public class Person extends Model {

    private String name;
    private Integer age;
    // getters and setters
}

PersonController.java

@RestController
@RequestMapping("/persons")
public class PersonController extends Controller<Person> {

    @GetMapping(value = {"/name/{name}"})
    public Person getByName(@PathVariable("name") String name) {
        // ...
    }
}

Когда я компилирую и пытаюсь запустить приложение, я получаю следующую ошибку: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'personsController'.Если я создаю класс

PersonRepository.java

public interface PersonRepository extends MongoRepository<Person, String> {}

или

public interface PersonRepository extends Repository<Person> {}

, приложение запускается без проблем.

1 Ответ

0 голосов
/ 19 октября 2018

Отвечая на мой собственный вопрос, я нашел решение, которое я могу использовать для генерации своих классов репозитория, и я мог бы даже расширить класс Controller.Я перестроил свой проект таким образом, чтобы я получил файл Model.java без изменений и с небольшим изменением Controller.java с

* 1006.*

до

protected MongoRepository<T, String> repository;

Я удалил пакет репозитория и добавил аннотации @RepositoryProperty в классе Person.

@RepositoryProperty
public class Person extends Model {

    private String name;
    private Integer age;
    // getters and setters
}

Затем создал новый проект maven синформация ниже.

pom.xml

<groupId>br.com.jadler</groupId>
<artifactId>processor</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>

<name>${project.build.finalName}</name>

<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
    <dependency>
        <groupId>com.google.auto.service</groupId>
        <artifactId>auto-service</artifactId>
        <version>1.0-rc1</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

RepositoryProperty.java

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface RepositoryProperty {
}

RepositoryProcessor.java

@SupportedAnnotationTypes("br.com.jadler.annotation.RepositoryProperty")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@AutoService(Processor.class)
public class RepositoryProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {

        annotations.forEach(a -> {
            env.getElementsAnnotatedWith(a).stream().forEach(e -> {
                write(e.toString());
            });
        });

        return true;
    }

    private void write(String name) {

        int index = name.lastIndexOf(".");
        String classname = name.substring(index + 1);
        String pkgname = name.substring(0, index);
        pkgname = pkgname.substring(0, pkgname.lastIndexOf("."));
        pkgname = pkgname + ".repository";

        try {

            StringBuilder builder = new StringBuilder();
            builder.append(String.format("package %s;%n%n", pkgname))
                   .append(String.format("import %s;%n", name))
                   .append(String.format("import  org.springframework.data.mongodb.repository.MongoRepository;%n%n"))
                   .append(String.format("public interface %sRepository extends MongoRepository<%s, String> {%n}%n", classname, classname));

            String source = String.format("%s.%sRepository", pkgname, classname);
            JavaFileObject file = processingEnv.getFiler().createSourceFile(source);
            Writer writer = new PrintWriter(file.openWriter());
            writer.write(builder.toString());
            writer.flush();
            writer.close();

        } catch (IOException ex) {
            System.err.println(ex.getMessage());
        }
    }
}

После этого я скомпилировал проект процессора и добавил его в качестве зависимости в исходном проекте.Я знаю, что могу сделать что-то похожее на контроллер, если ему, например, не нужен какой-то особый метод для PersonController.

Я выпущу этот проект в github и попытаюсь улучшить его, добавив аннотации дляконтроллер.

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