DAO 和服务层(JPA/Hibernate + Spring)
我正在设计一个基于 JPA/Hibernate、Spring 和 Wicket 的新应用程序。但我并不清楚 DAO 层和服务层之间的区别。根据维基百科,DAO 是
提供抽象的对象 某种类型数据库的接口或 持久化机制,提供一些 具体操作不暴露 数据库的详细信息。
我想知道 DAO 是否可以包含实际上与数据访问无关的方法,但使用查询更容易执行?例如“获取在特定机场运营的所有航空公司的列表”?在我看来,这更像是一种服务层方法,但我不确定在服务层中使用 JPA EntityManager 是否是一个好的实践示例?
I'm designing a new app based on JPA/Hibernate, Spring and Wicket. The distinction between the DAO and Service layers isn't that clear to me though. According to Wikipedia, DAO is
an object that provides an abstract
interface to some type of database or
persistence mechanism, providing some
specific operations without exposing
details of the database.
I was wondering whether a DAO could contain methods that don't really have to do much with data access, but are way easier executed using a query? For example "get a list of all airlines that operate on a certain set of airports"? It sounds to me to be more of a service-layer method, but I'm not sure if using JPA EntityManager in the service layer is an example of good practice?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
DAO 应该提供对单个相关数据源的访问,并且根据您的业务模型的复杂程度,将返回完整的业务对象或简单的数据对象。无论哪种方式,DAO 方法都应该在某种程度上密切反映数据库。
服务可以提供更高级别的接口,不仅可以处理您的业务对象,还可以首先访问它们。如果我从服务获取业务对象,该对象可能是从不同的数据库(和不同的 DAO)创建的,它可以用 HTTP 请求生成的信息进行修饰。它可能具有将多个数据对象转换为单个、健壮的业务对象的特定业务逻辑。
我通常创建一个 DAO,认为它将被任何要使用该数据库或一组业务相关数据的人使用,它实际上是数据库中除了触发器、函数和存储过程之外的最低级别代码。
具体问题的答案:
在大多数情况下,不,您会希望在服务层中使用更复杂的业务逻辑,即来自单独查询的数据的组装。但是,如果您担心处理速度,服务层可能会将操作委托给 DAO,即使它破坏了模型的美观,这与 C++ 程序员可能编写汇编代码来加速某些操作的方式非常相似。
如果您打算在服务中使用实体管理器,那么请将实体管理器视为您的 DAO,因为它就是这样。如果您需要删除一些冗余的查询构建,请不要在服务类中执行此操作,而是将其提取到利用实体管理器的类中,并将其设为您的 DAO。如果您的用例非常简单,您可以完全跳过服务层并使用实体管理器或控制器中的 DAO,因为您的所有服务要做的就是将对
getAirplaneById()
的调用传递给DAO 的 findAirplaneById()更新 - 为了澄清下面的讨论,在大多数情况下,在服务中使用实体管理器可能不是最佳决策,因为在大多数情况下还存在 DAO 层,原因如下:的评论。但在我看来,考虑到以下情况,这是完全合理的:
示例。
A DAO should provide access to a single related source of data and, depending on how complicated your business model, will return either full fledged Business objects, or simple Data objects. Either way, the DAO methods should reflect the database somewhat closely.
A Service can provide a higher level interface to not only process your business objects, but to get access to them in the first place. If I get a business object from a Service, that object may be created from different databases (and different DAO's), it could be decorated with information made from an HTTP request. It may have certain business logic that converts several data objects into a single, robust, business object.
I generally create a DAO thinking that it will be used by anyone who is going to use that database, or set of business related data, it is literally the lowest level code besides triggers, functions and stored procedures within the database.
Answers to specific questions:
for most cases no, you would want your more complicated business logic in your service layer, the assembly of data from separate queries. However, if you're concerned about processing speed, a service layer may delegate an action to a DAO even though it breaks the beauty of the model, in much the same way that a C++ programmer may write assembler code to speed up certain actions.
If you're going to use your entity manager in your service, then think of the entity manager as your DAO, because that's exactly what it is. If you need to remove some redundant query building, don't do so in your service class, extract it into a class that utilized the entity manager and make that your DAO. If your use case is really simple, you could skip the service layer entirely and use your entity manager, or DAO in controllers because all your service is going to do is pass off calls to
getAirplaneById()
to the DAO'sfindAirplaneById()
UPDATE - To clarify with regard to the discussion below, using an entity manager in a service is likely not the best decision in most situations where there is also a DAO layer for various reasons highlighted in the comments. But in my opinion it would be perfectly reasonable given:
example.
有一点是肯定的:如果你在service层使用EntityManager,你不需要dao层(只有一层应该知道实现细节)。除此之外,还有不同的观点:
所有需要的 dao 功能,所以他们
在服务中注入EntityManager
层。
由接口支持(因此服务
层与实现无关
细节)。
当涉及到关注点分离时,第二种方法更加优雅,并且它也将使从一种持久性技术切换到另一种更容易(您只需使用新技术重新实现 dao 接口),但如果您知道什么都没有会改变,第一个更容易。
我想说,如果您有一个小项目,请在服务层使用 JPA,但在大型项目中请使用专用的 DAO 层。
One thing is certain: if you use EntityManager on the service layer, you don't need a dao layer (only one layer should know implementation details). Apart from that, there are different opinions:
all needed dao functionality, so they
inject EntityManager in the service
layer.
backed by interfaces (so the service
layer is not tied to implementation
details).
The second approach is more elegant when it comes to separation of concerns and it also will make switching from one persistence technology to the other easier (you just have to re-implement the dao interfaces with the new technology), but if you know that nothing will change, the first is easier.
I'd say if you have a small project, use JPA in the service layer, but in a large project use a dedicated DAO layer.
Adam Bien 的这篇文章可能会有用。
This article by Adam Bien might be useful.
传统上,您将编写定义服务层和数据层之间契约的接口。然后您编写实现,这些就是您的 DAO。
回到你的例子。假设机场和航空公司之间的关系是多对多,并且有一个包含 airport_id 和 Airlines_id 的表,您可能有一个接口;
..并且您可以提供一个 Hibernate 实现;
您还可以考虑在航空公司实体上创建一个列表,并使用 @ManyToMany JPA 注释定义关系。这将完全消除这种特定 DAO 方法的必要性。
您可能还想研究用于编写 DAO 工厂的抽象工厂模式。例如;
此模式允许您的 HibernateDAOFactory 保存单个 EMF 并为各个 DAO 实例提供 EM。如果您不想走工厂路线,那么 Spring 非常擅长通过依赖注入为您处理 DAO 实例。
编辑:澄清了一些假设。
Traditionally you would write interfaces that define the contract between your service layer and data layer. You then write implementations and these are your DAOs.
Back to your example. Assuming the relationship between Airport and Airline is many to many with a table containing airport_id and airline_id you might have an interface;
..and you might provide a Hibernate implementation of this;
You could also look into having a List on your Airline entity and defining the relationship with a @ManyToMany JPA annotation. This would remove the necessity to have this particular DAO method altogether.
You might also want to look into the Abstract Factory pattern for writing DAO factories. For example;
This pattern allows your HibernateDAOFactory to hold a single EMF and supply individual DAO instances with EMs. If you don't want to go down the fatory route then Spring is great at handling DAO instances for you with dependancy injection.
Edit: Clarified a couple of assumptions.
Dao 是一个数据访问对象。它在数据库上存储/更新/选择实体。实体管理器对象用于此目的(至少在 open jpa 中)。您还可以使用此实体管理器运行查询。它不是 sql,而是 JPQL(Java 持久性查询语言)。
简单的例子:
Dao is a data access object. It does storing/updating/selecting entities on the database. The entity manager object is used for that (at least in open jpa). You can also run query's with this entity manager. It's no sql but JPQL (Java persistence query language).
Simple example: