Spring Data - 从存储库获取实体名称/类型

Tom*_*lik 4 java spring spring-data

我正在寻找一种从实现 Spring Data JPARepository接口的实例获取实体类型或类名的方法。

我有许多接口扩展了一个基本接口,该接口扩展了Repository接口并定义了一些基本查询。

@NoRepositoryBean
public interface EnumerationRepository<T extends IDatabaseEnumeration> extends Repository<T, String> {
    // ...
}

public interface SampleEnumerationRepository extends EnumerationRepository<SampleEnumeration> {

}
Run Code Online (Sandbox Code Playgroud)

Spring 允许我将所有这些接口的实现作为集合注入到 bean 中

@Autowired
private Collection<EnumerationRepository<? extends IDatabaseEnumeration>> repositories;
Run Code Online (Sandbox Code Playgroud)

我想将所有这些实现放入Map一个通用方法中以便于访问。我想使用实体类型或名称作为键,但我不确定从哪里获取它。有没有办法获得这些属性之一?最好是班级类型。

我能够通过这样的查询实现所需的行为。但如果可能的话,我想避免使用这种解决方案,因为它会创建对底层数据库的依赖。

@Query(value = "select '#{#entityName}' from dual", nativeQuery = true)
public String getEntityName();
Run Code Online (Sandbox Code Playgroud)

Tom*_*lik 6

@jens-schauder 的答案对我的情况不起作用,但它向我展示了正确的方向。

Spring 向我注入了扩展 spring 接口的接口的实现Repository。因此我必须获取所有接口,过滤掉 spring 内部的接口,所以我最终得到了我定义的接口。然而,这个还不是通用的,所以我必须获得具有通用类型的超级接口

我并不真正关心性能,因为这个方法仅在 Spring 容器初始化期间被调用。

幸运的是,多态性在这种情况下效果很好。所以我只需要在超级接口上实现默认方法。像这样

@NoRepositoryBean
public interface EnumerationRepository<T extends IDatabaseEnumeration> extends Repository<T, String> {

    // ...

    default Class<T> getEntityClass() {
        Type[] interfaces = getClass().getInterfaces();

        for (Type t : interfaces) {
            if (t instanceof Class<?>) {
                Class<?> clazz = (Class<?>) t;

                if (clazz.getPackage().getName().startsWith(ApplicationConst.BASE_PACKAGE)) {

                    // Repositories should implement only ONE interface from application packages

                    Type genericInterface = clazz.getGenericInterfaces()[0];

                    return (Class<T>) ((ParameterizedType) genericInterface).getActualTypeArguments()[0];
                }
            }
        }

        return null;
    }

}
Run Code Online (Sandbox Code Playgroud)

我希望这对面临类似问题的其他用户有用。