Java 在mvc体系结构(spring和hibernate)中,我应该在哪里实现特定的查询?

Java 在mvc体系结构(spring和hibernate)中,我应该在哪里实现特定的查询?,java,spring,hibernate,spring-mvc,Java,Spring,Hibernate,Spring Mvc,我正在使用SpringMVC和hibernate实现一个企业应用程序。应用程序体系结构由以下各层组成: 看法 控制器 服务 领域 周长 数据访问使用经典dao模式实现,并允许CRUD操作+通用查询。我应该在哪里实现特定查询?我想有两种解决办法: 通过创建hibernate条件并将其传递给持久性层,在服务层中实现特定的查询 通过为每个查询创建一个函数并调用服务层中的函数,在DAO类中实现特定的查询 我该怎么办?有更好的解决方案吗?最好将所有查询都放在DAO类方法中并运行它们。如果您正在使用

我正在使用SpringMVC和hibernate实现一个企业应用程序。应用程序体系结构由以下各层组成:

  • 看法
  • 控制器
  • 服务
  • 领域
  • 周长
数据访问使用经典dao模式实现,并允许CRUD操作+通用查询。我应该在哪里实现特定查询?我想有两种解决办法:

  • 通过创建hibernate条件并将其传递给持久性层,在服务层中实现特定的查询
  • 通过为每个查询创建一个函数并调用服务层中的函数,在DAO类中实现特定的查询

我该怎么办?有更好的解决方案吗?

最好将所有查询都放在DAO类方法中并运行它们。如果您正在使用HQL,请将所有查询写入NamedQuery,并在运行时按名称访问它

我用来创建一个
GenericDAO
类和一个
IDao
接口以及所有其他DAO,比如
ClientDAO
-扩展泛型


也就是说,我创建了一个扩展
IDao
的接口(它有一些基本方法,如
findAll()
delete()
save()


例如。

IClient ClientDaoImpl
public类ClientDaoImpl扩展GenericDao实现IClient{
公共void findWithWhere(字符串where){
//在这里做定制的东西
}
}
然后在控制器(或服务)层中有一个ClientDaoImpl对象

这可能看起来有点累,但对我来说,它可以很好地划分所有层,当我必须更改方法(可能接收新参数)时,我只需更改接口就可以知道我必须在何处实现。

从分层体系结构的角度来看,sql查询不应该在DAO层之外使用/声明。您可能已经注意到spring选择在服务层上使用事务,因为事务不是DAO的责任,您也可以将其称为资源泄漏/横切问题。在Dao之外声明/使用sql查询将被视为资源泄漏/横切问题


我想添加一些东西,因为您接触了hibernate和criteria API。当您使用条件时,为什么需要单独的查询?Criteria API是实现持久性的一种优雅方式,因为它是一种完美的OO方法。

服务层是一个业务层,并且不能使用任何与持久性提供程序相关的接口和类(即Hibernate Criteria API)。这是一个很好的实践——您可以更改持久性提供程序,而无需触及服务层中的任何代码行

不要犹豫使用第二个选项(在DAO类中实现特定的查询)

或者,您可以使用一种业务动态查询模式,它是查询构建器模式的混合体(如Criteria API)。下面是一个简单的例子:

interface CarQuery {
    CarQuery model(String model);
    CarQuery color(String color);
    List<CarQuery> execute(); 
}
....
List<Car> cars = carDao.getQuery().model("Jeep").color("green").execute();
....
接口查询{
CarQuery模型(字符串模型);
CarQuery颜色(字符串颜色);
List execute();
}
....
List cars=carDao.getQuery().model(“Jeep”).color(“绿色”).execute();
....
您可以实现可在内部使用Hibernate Criteria API的HibernateCarQuery。这当然需要一些额外的努力,但如果您计划广泛使用特定方法,并且需要动态构建查询的能力(典型的情况是UI页面上的多个过滤器),则不会污染DAO的特定方法。

  • 通过为每个查询创建一个函数并调用服务层中的函数,在DAO类中实现特定的查询
DAO是“数据访问对象”的缩写,使用DAO模式的主要原因之一是遵守“单一责任原则”。如果您的代码中有一些其他类,而不是处理数据访问的DAO类,那么您违反了SRP,使用DAO模式或多或少成为一个没有实际意义的问题

更重要的是,出于可维护性的目的,如果其他开发人员稍后要维护您的代码,并且他们看到大量的DAO类,那么他们不会期望在其他任何地方进行数据访问


您的服务层甚至不应该依赖于Hibernate。你为什么要那样?您的服务层应该只依赖于您的域层,而域层又依赖于您的持久性层,而持久性层正是您的Hibernate依赖性所在。

创建复杂的条件通常是您不希望在服务中,但在DAO中进行的与持久性相关的工作。如果DAO只包含Hibernate会话已有的基本方法,那么它们就不是真正有用的。这意味着在DAO类中创建许多非常简单和细粒度的函数,所以我想知道这是否是正确的方法。这是正确的方法。这样,您的服务可以专注于它的用途:业务逻辑。您可以通过模拟DAO来测试它。您可以在服务层中进行查询,但是,为了保持模式,我宁愿在DAO层中创建它们。我的解决方案与您的解决方案大致相同。关键是我有很多不同的细粒度查询需要实现,所以我必须在DAOs中实现很多简单的函数(或复杂的参数化函数),我不知道这是否是正确的方法,但当我谈论查询时,我的意思是为查询DB创建标准。我不使用单独的查询。问题是:我应该在服务层公开hibernate标准吗?这避免了我在DAOs中编写许多简单函数,但违反了层分离。我提到了资源泄漏。请取消
public class ClientDaoImpl extends GenericDao<Client> implements IClient {

  public void findWithWhere(String where) {
   //do custom stuff here
  }
}
interface CarQuery {
    CarQuery model(String model);
    CarQuery color(String color);
    List<CarQuery> execute(); 
}
....
List<Car> cars = carDao.getQuery().model("Jeep").color("green").execute();
....