我有两个类似的课程
@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);
}
}
如果仔细观察,您会发现两者看起来几乎相同。唯一的区别是它们都处理两个单独的对象。
所以总有写一个类来处理这种重复吗?
答案 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操作创建可重用机制。您应该在这些参数之间选择。如果您的应用程序小且不可扩展,则最好使用简单复制。