根据Spring Data Commons documentation,将自定义方法实现添加到Spring Data存储库非常简单:
interface UserRepositoryCustom {
public void someCustomMethod(User user);
}
class UserRepositoryCustomImpl implements UserRepositoryCustom {
public void someCustomMethod(User user) {
// Your custom implementation
}
}
public interface UserRepository extends JpaRepository<User, Long>,
UserRepositoryCustom {
}
然而,我无法弄清楚的是,如果你想使用类型参数怎么办?例如:
interface SearchableRepository<T> {
public Page<T> search(String query, Pageable page);
}
class SearchableRepositoryImpl<T> implements SearchableRepository<T> {
public Page<T> search(String query, Pageable page) {
// Right here, I need the Class<T> of T so that I can create
// the JPA query
}
}
public interface UserRepository extends JpaRepository<User, Long>,
SearchableRepository<User> {
}
public interface NewsRepository extends JpaRepository<Article, Long>,
SearchableRepository<Article> {
}
在search
方法的实现中,我需要知道提供的类型参数Class<T>
的{{1}},以便我可以创建JPA查询。我不想add custom behavior to all repositories,因为我不希望所有存储库都可以搜索。我只想应用T
接口来选择存储库。
那你怎么能这样做?或者你能做到吗?
答案 0 :(得分:2)
Bellabax的答案是正确的,让我走上了正确的轨道,所以他得到了赞誉和正确答案的功劳。但对于那些在这个问题上遇到困难的人来说,这是一个更完整的实现,可以自动发现域类型,不需要调用new
任何内容,并希望对某人有所帮助。
SearchableRepository.java
public interface SearchableRepository<T> {
public Page<T> search(String query, Pageable page);
}
AbstractDomainClassAwareRepository.java
class AbstractDomainClassAwareRepository<T> {
protected final Class<T> domainClass;
@SuppressWarnings("unchecked")
protected AbstractDomainClassAwareRepository() {
Type genericSuperclass = this.getClass().getGenericSuperclass();
while(!(genericSuperclass instanceof ParameterizedType))
{
if(!(genericSuperclass instanceof Class))
throw new IllegalStateException("Unable to determine type " +
"arguments because generic superclass neither " +
"parameterized type nor class.");
if(genericSuperclass == AbstractDomainClassAwareRepository.class)
throw new IllegalStateException("Unable to determine type " +
"arguments because no parameterized generic superclass " +
"found.");
genericSuperclass = ((Class)genericSuperclass).getGenericSuperclass();
}
ParameterizedType type = (ParameterizedType)genericSuperclass;
Type[] arguments = type.getActualTypeArguments();
this.domainClass = (Class<T>)arguments[0];
}
}
AbstractSearchableJpaRepository.java
class AbstractSearchableJpaRepository<T>
extends AbstractDomainClassAwareRepository<T>
implements SearchableRepository<T> {
@PersistenceContext protected EntityManager entityManager;
@Override
public Page<T> search(String query, Pageable page) {
// use this.domainClass to reference domain class
}
}
UserRepository.java
public interface UserRepository extends JpaRepository<User, Long>,
SearchableRepository<User> { }
UserRepositoryImpl.java
public class UserRepositoryImpl extends AbstractSearchableJpaRepository<User> { }
NewsRepository.java
public interface NewsRepository extends JpaRepository<Article, Long>,
SearchableRepository<Article> { }
NewsRepositoryImpl.java
public class NewsRepositoryImpl extends AbstractSearchableJpaRepository<Article> { }
答案 1 :(得分:1)
您可以将Class添加到SearchableRepositoryImpl并在NewsRepositoryImpl中注入(或创建)new SearchableRepositoryImpl(Article.class)
class SearchableRepositoryImpl<T> implements SearchableRepository<T> {
private Class<T> klass;
public SearchableRepositoryImpl(Class<T> klazz){
this.klass = klazz;
}
public Page<T> search(String query, Pageable page) {
// Right here, I need the Class<T> of T so that I can create
// the JPA query
}
}
class NewsRepositoryImpl<Article> implements NewsRepository<Article>
{
private SearchableRepository<Article> searchRepo = new SearchableRepositoryImpl(Article.class);
public Page<T> search(String query, Pageable page){
// delegate
return searchRepo.search(query, page);
}
}
也许new SearchableRepositoryImpl
不是真正的春天最好的实践,而只是为了展示这个想法