我正在寻找一种从实现Spring Data JPA Repository
接口的实例中获取实体类型或类名的方法。
我有许多接口扩展了扩展Repository
接口的基接口,并定义了一些基本查询。
@NoRepositoryBean
public interface EnumerationRepository<T extends IDatabaseEnumeration> extends Repository<T, String> {
// ...
}
public interface SampleEnumerationRepository extends EnumerationRepository<SampleEnumeration> {
}
Spring允许我将所有这些接口的实现作为集合注入到bean
中@Autowired
private Collection<EnumerationRepository<? extends IDatabaseEnumeration>> repositories;
我想将所有这些实现放入Map
,以便在泛型方法中轻松访问。我想使用实体类型或名称作为键,但我不知道从哪里得到它。有没有办法获得这些属性之一?最好是班级类型。
我能够通过这样的查询实现所需的行为。但是我想尽可能避免这种解决方案,因为它会创建对底层数据库的依赖。
@Query(value = "select '#{#entityName}' from dual", nativeQuery = true)
public String getEntityName();
答案 0 :(得分:2)
@ jens-schauder的答案在我的案例中没有用,但它向我展示了正确的方向。
Spring为我注入了扩展spring Repository
接口的接口的实现。因此,我必须得到所有接口,过滤掉弹簧内部接口,所以我最终得到了我定义的接口。然而,这个不是通用的,所以我必须得到具有泛型类型的它的超级接口。
我不太关心性能,因为只在Spring容器初始化期间调用此方法。
Fortunatelly多态在这种情况下运作良好。所以我只需要在超级接口上实现默认方法。喜欢这个
@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;
}
}
我希望这对面临类似问题的其他用户有用。
答案 1 :(得分:1)
如果类型参数绑定到接口中的类型,则可以使用以下答案获取类型参数:https://stackoverflow.com/a/1901275/66686
Index id user_id merchant_id marketing_email_id start_date end_date email_status sms_status created_at visited_at
0 68989 68990 13277 38 437 2016-04-11 00:00:00 2016-04-16 00:00:00 1 NaN 2016-04-11 11:05:31 []
1 403557 403558 195246 179 2218 2017-06-09 00:00:00 2017-06-12 00:00:00 0 1 2017-06-09 06:01:04 []
2 333381 333382 127359 514 1820 2017-04-24 00:00:00 2017-05-01 00:00:00 0 1 2017-04-24 10:00:33 ['2017-04-24']
3 511815 511816 151653 259 1136 2017-08-05 00:00:00 2017-08-08 00:00:00 0 1 2017-08-05 11:31:19 []
4 167172 167173 51546 32 363 2016-08-05 00:00:00 2016-08-15 00:00:00 1 NaN 2016-08-05 12:00:43 []
答案 2 :(得分:0)
尝试一下
import com.fasterxml.classmate.ResolvedType;
import com.fasterxml.classmate.TypeResolver;
import org.springframework.aop.support.AopUtils;
import org.springframework.data.repository.Repository;
import org.springframework.util.Assert;
import java.util.List;
public class Repospector {
private static final TypeResolver RESOLVER = new TypeResolver();
public Class<?> getEntityClass(Repository<?, ?> repository) {
Class<?> targetClass = AopUtils.getTargetClass(repository);
List<ResolvedType> types = RESOLVER.resolve(targetClass).typeParametersFor(Repository.class);
Assert.state(types.size() == 2, "Call the whambulance!");
return types.get(0).getErasedType();
}
}