1

根据 Spring Data Commons文档,将自定义方法实现添加到 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>提供的类型参数的类型T,以便创建 JPA 查询。我不想向所有存储库添加自定义行为,因为我不希望所有存储库都可搜索。我只想将SearchableRepository界面应用于选择存储库。

那么你怎么能做到这一点呢?或者你能做到吗?

4

2 回答 2

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
    }
}

用户存储库.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> { }
于 2013-08-08T03:54:45.530 回答
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并不是真正的春季最佳实践,而只是为了展示这个想法

于 2013-08-07T18:15:48.813 回答