我有一个关于在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();
不使用第二种方法的主要问题是什么?
答案 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!
}
一些一般性的建议:
最后,我在您的示例中进行的一项小改动是使用MyDbService
注释@Component
而不是@Repository
。 @Repository
应仅限于DAO。
希望漫无边际!
答案 1 :(得分:2)
在您的情况下,中间层已过时。如果您只是重新公开依赖项(无论如何都是反模式)或发现自己做了什么,只是委托给依赖项,只需将依赖项注入您的客户端。所以例如我认为从SpringMVC控制器等使用存储库可能是绝对可以的。
但是有两件事需要考虑:
我们通常不建议扩展JpaRepository
,因为它暴露了JPA特定的方法,客户端实际上不应该知道底层的持久性技术。所以请使用CrudRepository
,PagingAndSortingRepository
等。
当你需要编排多个调用时,肯定做使用中间层,因此可能需要划分更广泛的事务边界。或者,如果您想避免客户端直接使用存储库,请在服务中使其受保护包和更高级别的方法,这可能会执行其他业务功能(例如密码编码等)