Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在春季向客户公开JpaRepository可以吗?_Java_Spring_Jpa_Spring Data_Spring Data Jpa - Fatal编程技术网

Java 在春季向客户公开JpaRepository可以吗?

Java 在春季向客户公开JpaRepository可以吗?,java,spring,jpa,spring-data,spring-data-jpa,Java,Spring,Jpa,Spring Data,Spring Data Jpa,我有一个关于JpaRepository在春季使用的概念性OO问题。只向调用者公开JpaRepository并让他们在该实例上调用CRUD方法可以吗,或者我必须包装每个方法并仅从服务中调用相应的JpaRepository方法 代码: public interface MyJpa extends JpaRepository<MyEntity, Long> 然后客户会做: Iterable<MyEntity> entities = myDbService.findAll();

我有一个关于JpaRepository在春季使用的概念性OO问题。只向调用者公开JpaRepository并让他们在该实例上调用CRUD方法可以吗,或者我必须包装每个方法并仅从服务中调用相应的JpaRepository方法

代码:

public interface MyJpa extends JpaRepository<MyEntity, Long>
然后客户会做:

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

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

我更喜欢后一种方法。在我处理的应用程序中,我通常有以下几层(可能有更多或更少的层-这是一个非常粗略的指南):

第1层-客户端层

可能是Spring MVC
@控制器
@服务
。例如:

@Controller
public class MyController {
  @Autowired private MyManager myManager; // see Layer 2
}
第2层-业务层

第2层提供了客户端层和DAO之间的分离。它通常是一个超过1个或多个DAO的立面。您可以将业务逻辑/规则放在这里,也可以委托或添加另一层。例如:

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

第3层是DAO或
@存储库
类。根据你的例子:

public interface MyDao extends JpaRepository<MyEntity, Long> {
  // Spring Data JPA magic here!
}
公共接口MyDao扩展了JpaRepository{
//春天数据JPA魔术在这里!
}
一些一般性建议:

  • 没有严格的规定,每个应用程序都是不同的。在应用程序需求的上下文中做对您有意义的事情
  • 每一层只应承担一项责任。如果您发现一个具有多个职责(例如数据访问和客户端API)的层,那么最好将其拆分为两个
最后,在您的示例中,我要做的一个小改动是使用
@Component
注释
MyDbService
,而不是
@Repository
<代码>@Repository应仅限于DAO


希望这漫无边际的谈话有意义

在您的情况下,中间层已过时。如果您只是公开依赖项(无论如何,这是一种反模式),或者发现自己在做任何事情,而不是委托给依赖项,那么只需将依赖项注入到您的客户机中。例如,我认为从SpringMVC控制器等使用存储库是完全可以的

但是,有两件事需要考虑:

  • 我们通常不建议扩展
    JpaRepository
    ,因为它公开了特定于JPA的方法,客户端实际上不应该知道底层的持久性技术。因此,应该使用
    crudepository
    分页和排序存储库

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


  • 谢谢你的回复。是的,就层次而言,我做的几乎相同。我的问题可能更多的是关于你的图层有多不透明。也就是说,第1层只能从第2层调用API,或者第1层可以从第2层获取第3层的实例,然后与之交互。看来违反层间隔离可能是不使用getJpa()方法的原因之一。@DennisK是的,我总是将层1和层3分开!这绝对违反了每层责任原则。有趣的是,这是我偶尔遇到的关于弹簧和自动布线的事情。获取任何Spring管理类的实例都太容易了。谢谢,Oliver。是的,这种方法是可行的,但前提是您的存储库只有一个客户机。#1中的另一个要点。实际上,让我想到这个问题的是一个服务,它结合了几个相互关联的表(比如A、B和C),除了CRUD之外,它只公开了一些特定的方法,比如“按A.id和C.timestamp获取B.name”。重新映射CRUD方法会使这个类成为许多样板代码的容器。因此,让CRUD方法可以通过myDbService.getACRUD()、.getBCRUD()、.getCCRUD()访问,然后只向服务本身添加特定的复杂请求,可以使类更加简洁易读。。。
    @Component
    public class MyManagerImpl implements MyManager {
      @Autowired private MyDao myDao; // see layer 3
    }
    
    public interface MyDao extends JpaRepository<MyEntity, Long> {
      // Spring Data JPA magic here!
    }