提问者:小点点

Spring Boot/Data:crud操作的通用服务类


假设我想创建一个RESTAPI,它对多个实体执行基本的CRUD操作。为此,我创建了通用接口:

public interface CrudService<T>{
    //generic CRUD methods
}

及其对Foo实体的实现:

@Entity
public class Foo {
}

@Repository
public interface FooRepository extends JpaRepository<Foo, Long>{
}

@Service
@Transactional
public class FooCrudServiceImpl implements CrudService{

    @Autowired
    private FooRepository repository;

    //CRUD methods implementation
}

@RestController
class FooController{
    @Autowired
    private CrudService<Foo> crudService;

    //Controller methods
}

我现在想避免的是为每个实体创建具有基本相同逻辑的服务实现。所以我尝试创建一个可以从多个控制器(FoController、BarController等)调用的通用服务类:

@Service
@Transactional
class GenericCrudServiceImpl<T> implements CrudService{

    @Autowired
    private JpaRepository<T, Long> repository;

    //generic CRUD methods implementation
}

并将该服务类传递给将指定实体类型的每个控制器。问题是会有多个存储库bean可以注入到GenericCrudServiceImpl(fooRepository,BarRepository等)中,并且仅仅通过指定JpaRepositorySpring的类型仍然不知道要注入哪个bean。我不想直接从控制器类调用存储库bean来保持职责分离。

此外,由于某种原因,这个问题不会发生在控制器级别,在那里我注入CrudService接口并且Spring知道它应该选择哪个bean,这与我对依赖注入的整体理解相混淆。

有没有办法创建这样一个通用的服务类?stackoverflow上的其他帖子没有给我提供答案。

额外的问题:使用@Qualifier注释和注入特定实现有什么区别(在本例中FoCrudServiceImpl而不是控制器类中的CrudService)?在这两种情况下,指向不同的使用实现都需要更改一行代码。


共1个答案

匿名用户

那个怎么样:

@Transactional
public class GenericCrudServiceImpl<T> implements CrudService{
   private JpaRepository<T, Long> repository;

   public GenericCrudServiceImpl(JpaRepository<T, Long> repository) {
      this.repository = repository;
   }
}

和Spring配置:

@Configuration
public PersistanceConfiguration {
   @Bean
   public JpaRepository<Foo, Long> fooJpaRepository() {
      ...
   }

   @Bean
   public JpaRepository<Foo, Long> booJpaRepository() {
      ...
   }

   @Bean
   public CrudService<Foo> fooService(JpaRepository<Foo, Long> fooJpaRepository) {
      return new GenericCrudServiceImpl(fooJpaRepository);
   }

   @Bean
   public CrudService<Foo> booService(JpaRepository<Foo, Long> booJpaRepository) {
      return new GenericCrudServiceImpl(booJpaRepository);
   }
}

和控制器

@RestController
class FooController{
       
   // Injection by bean name 'fooService'
   @Autowired
   private CrudService<Foo> fooService;
    
   //Controller methods
}