如何将两种服务合而为一

时间:2019-03-29 14:47:11

标签: spring spring-mvc

我有两个类似的课程

@Service
class BookService {
    @Autowired 
    BookRepository repository;

    public Book findById(Long id){
        Book book =  repository.findById(id);
        if (book==null){
            throw new EntityNotFoundException("Entity Not found with given id: "+id);
        }
        return book;
    }

    public Book save(Book book){
        return repository.save(book);
    }
}



@Service
class AuthorService {
    @Autowired
    AuthorRepository repository;

    public Author findById(Long id){
        Author author =  repository.findById(id);
        if (author==null){
            throw new EntityNotFoundException("Entity Not found with given id: "+id);
        }
        return author;
    }

    public Author save(Author author){
        return repository.save(author);
    }
}

如果仔细观察,您会发现两者看起来几乎相同。唯一的区别是它们都处理两个单独的对象。

所以总有写一个类来处理这种重复吗?

2 个答案:

答案 0 :(得分:2)

使用对象编程逻辑:

   @Service
    class RepService {
        IRepository = repositoryClass;

        public T FindById<T>(Long id) where T : class {
            T findItem =  repository.findById(id);
            if (author==null){
                throw new EntityNotFoundException("Entity Not found with given id: "+id);
            }
            return findItem;
        }

        public T Save<T>(T obj) where T : class {
             return repository.Save(obj);
        }
    }

然后,您需要BookRepository和AuthorRepository来实现IRepository。他们还需要在构造函数中初始化各自的repositoryClass。

答案 1 :(得分:1)

您可以使用默认逻辑创建通用的CrudService<T, ID>CrudAbstractService<T, ID>来存储/检索类似的对象。

public interface CrudService<T, ID> {
    T save(T entity);

    T find(ID id);
}

public abstract class CrudAbstractService<T, ID> implements CrudService<T, ID> {

    private final JpaRepository<T, ID> repository;

    public CrudAbstractService(JpaRepository<T, ID> repository) {
        this.repository = repository;
    }

    @Override
    public T save(T entity) {
        return repository.save(entity);
    }

    @Override
    public T find(ID id) {
        return repository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("Entity Not found with given id: " + id));
    }

}

然后使用此逻辑扩展您的BookService或任何其他服务

public interface BookService extends CrudService<Book, Long> {
    // service-specific methods for example findBooksByAuthor(String author);
}
@Service
public class BookServiceImpl extends CrudAbstractService<Book, Long> implements BookService {

    private final BookRepository repository;

    @Autowired
    public BookServiceImpl(BookRepository repository) {
        super(repository);
        this.repository = repository;
    }

    // implement here service-specific logic from BookService interface

}

然后,您可以为这些操作创建CrudController,并在整个实体中使用它。

public abstract class CrudController<T, ID> implements CrudService<T, ID> {

    private final CrudService<T, ID> service;

    public CrudController(CrudService<T, ID> service) {
        this.service = service;
    }

    @PostMapping
    public T save(@RequestBody T entity) {
        return service.save(entity);
    }

    @GetMapping("/{id}")
    public T find(@PathVariable ID id) {
        return service.find(id);
    }
}
@RestController
@RequestMapping("/books")
public class BookController extends CrudController<Book, Long> {

    private final BookService service;

    @Autowired
    public BookController(BookService service) {
        super(service);
        this.service = service;
    }
    // other BookService specific logic
}

注意,这种方法可能会增加代码的复杂度,但是它会减少重复并为CRUD操作创建可重用机制。您应该在这些参数之间选择。如果您的应用程序不可扩展,则最好使用简单复制