可以将Spring中的JpaRepository暴露给客户端吗?

时间:2012-12-09 21:48:09

标签: java spring jpa spring-data spring-data-jpa

我有一个关于在Spring中使用JpaRepository的概念性OO问题。是否可以将JpaRepository暴露给调用者并让它们在该实例上调用CRUD方法,或者我必须包装每个方法并仅从服务中调用相应的JpaRepository方法?

在代码中:

public interface MyJpa extends JpaRepository<MyEntity, Long>

然后:

@Repository
public class MyDbService{

    @Autowired
    private MyJpa myJpa;

    public Iterable<MyEntity> findAll()
    {
        return myJpa.findAll()
    }

    ... other CRUD methods

}

然后客户会这样做:

Iterable<MyEntity> entities = myDbService.findAll();

相反:

@Repository
public class MyDbService{

    @Autowired
    private MyJpa myJpa;

    public MyJpa getJpa() {
        return myJpa 
    };
}

然后客户会这样做:

Iterable<MyEntity> entities = myDbService.getJpa().findAll();

不使用第二种方法的主要问题是什么?

2 个答案:

答案 0 :(得分:4)

我更喜欢后一种方法。在我工作的应用程序中,我通常有以下图层(可能有更多或更少的图层 - 这是一个非常粗略的准则):

第1层 - 客户端层

也许是Spring MVC @Controller@Service。例如:

@Controller
public class MyController {
  @Autowired private MyManager myManager; // see Layer 2
}

第2层 - 业务层

第2层提供客户端层和DAO之间的分离。它通常是一个或多个DAO的外观。您可以将业务逻辑/规则放在此处,或委派或添加其他层。例如:

@Component
public class MyManagerImpl implements MyManager {
  @Autowired private MyDao myDao; // see layer 3
}

第3层 - DAO层

第3层是您的DAO或@Repository类。根据你的例子:

public interface MyDao extends JpaRepository<MyEntity, Long> {
  // Spring Data JPA magic here!
}

一些一般性的建议:

  • 没有严格的规则,每个应用程序都不同。在您的应用程序要求的上下文中对您做有意义的事情
  • 每一层应该只有一个责任。如果您发现具有多个职责的层(例如数据访问和客户端API),那么最好将其拆分为两个

最后,我在您的示例中进行的一项小改动是使用MyDbService注释@Component而不是@Repository@Repository应仅限于DAO。

希望漫无边际!

答案 1 :(得分:2)

在您的情况下,中间层已过时。如果您只是重新公开依赖项(无论如何都是反模式)或发现自己做了什么,只是委托给依赖项,只需将依赖项注入您的客户端。所以例如我认为从SpringMVC控制器等使用存储库可能是绝对可以的。

但是有两件事需要考虑:

  1. 我们通常不建议扩展JpaRepository,因为它暴露了JPA特定的方法,客户端实际上不应该知道底层的持久性技术。所以请使用CrudRepositoryPagingAndSortingRepository等。

  2. 当你需要编排多个调用时,肯定使用中间层,因此可能需要划分更广泛的事务边界。或者,如果您想避免客户端直接使用存储库,请在服务中使其受保护包和更高级别的方法,这可能会执行其他业务功能(例如密码编码等)