Java Spring Boot如何实现业务逻辑层和资源库层?

Posted

技术标签:

【中文标题】Java Spring Boot如何实现业务逻辑层和资源库层?【英文标题】:How to implement the Business Logic layer and the Repository Layer with Java Spring Boot? 【发布时间】:2018-12-18 22:27:44 【问题描述】:

我正在尝试为我的应用程序创建业务逻辑(服务)和存储库(数据访问)层。我想正确地做到这一点,但我不是专家。

目前,对于 Repository 层,我创建了一个扩展 JpaRepository 的接口 IMainDao

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface IMainDao extends JpaRepository<Object, Integer>

所以我所有的存储库接口都可以扩展 IMainDao:

import org.springframework.stereotype.Repository;

@Repository
public interface IUserDao extends IMainDao


我还创建了业务逻辑层。一个接口IMainService

import java.util.List;
import org.springframework.stereotype.Service;

@Service
public interface IMainService 

    Object getById(int id);
    List<Object> getAll();
    Object create(Object o);
    Object update(Object o);
    void delete(int id);

这个接口MainService

的实现
@Service
public class MainService implements IMainService

    @Autowired
    private IMainDao mainDao;

    @Override
    public Object getById(int id) 
        return mainDao.findById(id);
    

    @Override
    public List<Object> getAll() 
        return mainDao.findAll();
    

    @Override
    public Object create(Object o)        
        Object obj = mainDao.save(o);     
        return obj;
    

//Other methods...

以及扩展 IMainService 的其他接口,如 IUserService

import org.springframework.stereotype.Service;

@Service
public interface IUserService extends IMainService


他们的实现:

public abstract class UserService implements IUserService


我做得对吗?如果没有,你有什么推荐给我的,我可以在哪里优化?

谢谢!

【问题讨论】:

我想创建我的其他接口,而不必在其实现中重新创建方法。 好吧,第一个春天不是这样工作的。 JpaRepository 需要知道它正在处理什么实体类型,放入 Object 是行不通的。如果您注入的所有内容都具有相同的类型,则无法按类型自动连接。 谢谢,我明白了。我删除了 IMainDao,所以我所有的存储库都扩展了 JpaRepository。但是,关于服务,我想避免在他们的实现中重新创建像 public Object getById(int id) return mainDao.findById(id); 这样的方法 @Johna 说 IMainDao 是不必要的。您可以直接从 JpaRepository 扩展您的存储库。服务类是您放置业务逻辑的地方。您实际上在做的是在服务类中编写业务逻辑并提供适配器来访问存储库的那些,因此您的适配器是存储库接口。 【参考方案1】:

您的IMainDao 似乎没有必要。您可以根据需要为实体定义接口,例如:User, Order

@Repository
interface UserRepository extends JpaRepository<User, Long> 

@Repository
interface OrderRepository extends JpaRepository<Order, Long> 

而且,在您的业务逻辑层中,您可以拥有服务接口及其实现,例如:

@Service
interface UserService
    ... method declarations goes here
 

class UserServiceImpl implements UserService 
   @Autowired
   UserRepository userRepository;     

   ... implement interface methods 
 

如果你在多个服务类中有通用方法,你可以有一个通用的服务接口,否则IMainService没有意义。

==== [编辑] 介绍通用服务接口 ====

假设UserServiceOrderService 都有共同的搜索方法。然后我们可以有一个通用的服务接口(@98​​7654328@)并在需要的服务实现类中实现它。

interface SearchService<T, I> 
  T findLatestOne()
  T lastEditedOne()
  List<T> searchByKeywords    


class UserService implements SerchService<User, Long> 
  User findLatestOne() ... implementation 
  User lastEditedOne() ... implementation 
  List<User> searchByKeywords ... implementation 


class OrderService implements SerchService<Order, Long> 
  Order findLatestOne() ... implementation 
  Order lastEditedOne() ... implementation 
  List<Order> searchByKeywords ... implementation 

【讨论】:

谢谢,我明白了。我删除了 IMainDao,所以我所有的存储库都扩展了 JpaRepository。通用服务接口是什么意思。你能给我举个例子吗? 请查看编辑部分,了解如何在业务逻辑层拥有通用服务接口的示例。 我已经阅读了一些教程,你的权利,最好的方法是使用泛型类。但是,在您的示例中,我必须为所有服务实现每种方法,并且这些方法执行相同的工作。我想要一个实现SearchService 的类,以便服务可以扩展它。问题是,我没有可以在此类中使用的通用 DAO。谢谢! 如果您发现业务逻辑类之间的搜索方法相似,您可以将SerachService 设为抽象类并在相关类中进行扩展。【参考方案2】:

我建议根据您的实体模型的需要定义存储库。

@Repository
public interface IUserDao extends JpaRepository<User, Long>

实现的 API 将调整为定义的泛型。

关于服务,请遵循该方法;依赖注入的存储库,向接口开发并实现它们以提供具体功能。虽然,尽量避免在服务中继承;大多数情况下,这并不是真正需要的,除非确实有特定的保证,比如通用逻辑,应该通过泛型进行调整以适应服务的具体情况。

【讨论】:

感谢您的回答。我了解存储库。在我的服务中,我想避免在其实现中重新创建像 public Object getById(int id) return mainDao.findById(id); 这样的方法。我该怎么办? 我认为你必须牺牲实体模型的设计来实现这样的目标。这将有助于您的设计并使您的代码更易于理解

以上是关于Java Spring Boot如何实现业务逻辑层和资源库层?的主要内容,如果未能解决你的问题,请参考以下文章

java spring boot代码分层每层业务为何分层

谈谈对spring boot分层中各层的理解

在 Spring Boot 中,如何干掉 if else!

关于Spring Boot中的业务层(Service)是否要创建接口的分析

Spring Boot 2 实践记录之 条件装配

基于Spring4+Hibernate4的通用数据访问层+业务逻辑层(Dao层+Service层)设计与实现!