有没有一种方法可以创建扩展MongoRepository的通用接口?

时间:2018-10-18 18:48:14

标签: java spring-boot generics repository

给出以下代码,有没有一种方法可以创建可用于所有实体的通用存储库接口?

我有这种情况:

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 :(得分:-1)

回答我自己的问题,我找到了一个可用于生成我的Repository类的解决方案,甚至可以扩展到Controller类。我所做的就是重组项目,最终得到了 Model.java 文件,没有任何更改,而 Controller.java 中的

略有变化。 >
protected Repository<T> repository;

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的任何特定方法,我可以做与Controller类似的事情。

我将这个项目发布到github中,并尝试对其进行改进以为Controller添加注释。