【问题标题】:Spring Data JPA How to build a generic Repository for multiple entities? [duplicate]Spring Data JPA 如何为多个实体构建通用存储库? [复制]
【发布时间】:2018-11-08 14:04:01
【问题描述】:

我开始使用 Spring Data JPA 存储库。我们已经有一个使用 Spring MVC(没有 spring boot 或 spring data JPA)的应用程序,我们在其中编写了一个 Generic DAO 类来处理我们拥有的几乎所有实体的基本 CRUD 操作。任何其他特殊操作都可以通过编写自定义 DAO 来处理。

现在,Spring data JPA 让事情变得非常简单,只需要我们编写一个接口,剩下的就交给我们了。

public interface PersonRepository extends JpaRepository<Person, Long> {

}

这很酷,但我想知道是否可以在这里介绍泛型。

原因是,我的应用程序有许多实体,我们只需要对其执行基本的 CRUD 操作,仅此而已。这意味着,对于每个实体,我们都需要编写一个接口。虽然代码很少,但它会为每个实体生成一个文件,我想这是可以避免的(真的吗?)。

我的问题是,我可以写一个通用的 Repository 类吗

public interface GenericRepository<T> extends JpaRepository<T, Long> {

}

这样我的服务类可以看起来像这样

@Autowired
private GenericRepository<Person> personRepository;

public List<Person> findAll() {
     return this.personRepository.findAll();
}

对于基本操作,这将是一种更简洁的方法,因为一个存储库接口可以处理多个实体。

编辑 事实证明,我确实可以创建一个如上图所示的存储库接口,但是当应用程序启动时,我收到一个错误提示

Error creating bean with name 'genericRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class java.lang.Object

这可能是因为通用类型

我不得不说我的实体本身就是独立的类,并且不实现或扩展超级实体/实体。如果他们这样做会有帮助吗?

请指引我正确的方向。

谢谢!

【问题讨论】:

标签: java generics spring-data-jpa


【解决方案1】:

我认为你可以这样做:

@NoRepositoryBean
public interface GenericRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
   //added custom common functionality for all the GenericRepository implementations
   public List<T> findByAttributeContainsText(String attributeName, String text);
}

public class GenericRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
    implements GenericRepository<T, ID> {

   private EntityManager entityManager;

   public GenericRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
    super(entityInformation, entityManager);
    this.entityManager = entityManager;
}

@Transactional
public List<T> findByAttributeContainsText(String attributeName, String text) {
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<T> cQuery = builder.createQuery(getDomainClass());
    Root<T> root = cQuery.from(getDomainClass());
    cQuery.select(root).where(builder.like(root.<String>get(attributeName), "%" + text + "%"));
    TypedQuery<T> query = entityManager.createQuery(cQuery);
    return query.getResultList();
}
}
public interface MyOtherRepository extends GenericRepository<Role, Long> {

}

在你的配置类中:

@Configuration
@EnableJpaRepositories(basePackages="com.myProject", repositoryBaseClass = 
GenericRepositoryImpl.class)
public class JpaConfig {

}

【讨论】:

  • 服务方法不应该用@Transactional而不是repo注解吗?
猜你喜欢
  • 1970-01-01
  • 2017-12-02
  • 2016-12-30
  • 2018-06-15
  • 2013-05-09
  • 2019-05-10
  • 1970-01-01
  • 2019-08-07
  • 1970-01-01
相关资源
最近更新 更多