[英]Where should I implement specific queries in mvc architecture(spring + hibernate)?
I'm implementing an enterprise application using spring mvc and hibernate. 我正在使用spring mvc和hibernate实现一个企业应用程序。 The application architecture is composed by the following layers:
应用程序体系结构由以下层组成:
The data access is implemented with classic dao pattern and allows CRUD operations + generic queries. 数据访问使用经典dao模式实现,并允许CRUD操作+通用查询。 Where should I implement specific queries?
我应该在哪里实现特定查询? I guess two solutions:
我想两个解决方案:
What should I do? 我该怎么办? Are there better solutions?
有更好的解决方案吗?
Service layer is a business layer and there must not be used any persistence provider related interfaces and classes (ie Hibernate Criteria API). 服务层是业务层 , 不得使用任何与持久性提供程序相关的接口和类(即Hibernate Criteria API)。 That's a good practice - you can change your persistence provider without touching any line of code in your service layer.
这是一个很好的做法 - 您可以更改持久性提供程序,而无需触及服务层中的任何代码行。
Don't hesitate to go with your second option (implement specific queries in DAO classes). 不要犹豫,使用第二个选项(在DAO类中实现特定查询)。
Alternatively you can use kind of business dynamic query pattern which is mix of the query and builder pattern (like Criteria API). 或者,您可以使用一种业务动态查询模式,它是查询和构建器模式的混合(如Criteria API)。 Here is the simple example:
这是一个简单的例子:
interface CarQuery {
CarQuery model(String model);
CarQuery color(String color);
List<CarQuery> execute();
}
....
List<Car> cars = carDao.getQuery().model("Jeep").color("green").execute();
....
You can implement HibernateCarQuery that can use Hibernate Criteria API internally. 您可以实现HibernateCarQuery可以在内部使用Hibernate API标准。 This surely requires some additional efforts but will not pollute your daos with specific methods if you're planning to use them extensively and need ability to build queries dynamically (typical case is multiple filters on UI pages).
这肯定需要一些额外的努力,但如果您计划广泛使用它们并且需要能够动态构建查询(典型情况是UI页面上的多个过滤器),则不会使用特定方法污染您的daos。
From layered architecture perspective, the sql queries should not be used/declared outside DAO layer. 从分层体系结构的角度来看,不应在DAO层之外使用/声明sql查询。 You might have noticed that spring opted to use transaction on service layer since transaction is not the responsibility of DAO and you can also call it as resource leakage/cross cutting concern.
您可能已经注意到spring选择在服务层上使用事务,因为事务不是DAO的责任,您也可以将其称为资源泄漏/交叉问题。 Declaring /using sql queries apart from Dao will be considered to be resource leakage/cross cutting concern.
声明/使用除Dao之外的sql查询将被视为资源泄漏/交叉问题。
I would like to add something since you touched hibernate and criteria API. 我想添加一些东西,因为你触及了hibernate和标准API。 When you are using criteria then why should you need separate query?
当您使用标准时,为什么还需要单独的查询? Criteria API is an elegant way to achieve persistence because it is perfect OO approach.
Criteria API是一种实现持久性的优雅方式,因为它是完美的OO方法。
This: 这个:
DAO is shorthand for "Data Access Object" and one of the maim reasons to use the DAO pattern is to comply with the "Single Responsibility Principle". DAO是“数据访问对象”的简写,使用DAO模式的一个主要原因是遵守“单一责任原则”。 If you have some other classes in your code, other than the DAO classes, which handle Data Access, then you are violating the SRP and it becomes a more or less moot point to use the DAO pattern at all.
如果您的代码中有一些其他类,除了处理数据访问的DAO类,那么您违反了SRP,并且根本就没有使用DAO模式。
More importantly, for maintainability purposes, if other developers are going to maintain your code later on, and they see a bunch of DAO classes lying about, they are not going to expect data access to be happening anywhere else. 更重要的是,出于可维护性的目的,如果其他开发人员稍后要维护您的代码,并且他们看到一堆DAO类,那么他们就不会期望在其他地方发生数据访问。
Your service layer isn't even supposed to have a dependency on Hibernate. 您的服务层甚至不应该依赖于Hibernate。 Why would you have that?
你为什么要这样? Your service layer should only depend on your domain layer, which in turn depends on your persistence layer, which is where your Hibernate dependency should be,
您的服务层应该只依赖于您的域层,而域层又取决于您的持久层,这是您的Hibernate依赖项所在的位置,
It is better to have all the queries in the DAO class methods and run them. 最好在DAO类方法中包含所有查询并运行它们。 If you are working on HQL, have all the queries written in the NamedQuery and access it by name at the run time.
如果您正在使用HQL,请在NamedQuery中编写所有查询,并在运行时按名称访问它。
I use to create a GenericDAO
class and an IDao
interface and all the other DAOs - let's say a ClientDAO
- extends the Generic. 我用来创建一个
GenericDAO
类和一个IDao
接口以及所有其他DAO - 假设一个ClientDAO
- 扩展了Generic。
That being said, I create an interface that extends IDao
(which have the basics methods like findAll()
, delete()
, save()
) 话虽这么说,我创建了一个扩展
IDao
的接口(其中包含基本方法,如findAll()
, delete()
, save()
)
Eg 例如
public interface IClient extends IDao {
public void findWithWhere(String where);
}
public class ClientDaoImpl extends GenericDao<Client> implements IClient {
public void findWithWhere(String where) {
//do custom stuff here
}
}
And then have a ClientDaoImpl object in the Controller (or Service) Layer 然后在Controller(或服务)层中有一个ClientDaoImpl对象
That may look a little tiring to do, but, for me, it keeps all the layers well divided and when I have to change a method (maybe receive a new parameter), I simple change the interface to know where I have to implement. 这可能看起来有些累人,但是,对我来说,它保持所有层次分工,当我必须更改方法(可能接收新参数)时,我简单地更改界面以了解我必须实现的位置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.