简体   繁体   English

存储库模式的好处和Spring的实现

[英]Repository pattern benefits and Spring implementation

In the article Don't use DAO, use Repository there is a pretty good explanation of the differences between DAO and repository patterns. 在文章中不要使用DAO,使用Repository可以很好地解释DAO和存储库模式之间的差异。

My brief retelling - DAO makes us to bloat interface with multiple methods, which obstruct changes and testing. 我简短的复述 - DAO让我们用多种方法膨胀界面,这阻碍了变化和测试。 In turn, repository encapsulate all customizations/changes with query method, which accept Specification as an argument. 反过来,存储库使用query方法封装所有自定义/更改, query方法接受Specification作为参数。 When you need a new behavior at repository - you shouldn't change it, instead create a new heir of Specification . 当您在存储库中需要新行为时 - 您不应该更改它,而是创建一个新的Specification继承人。

My conslusion - repository pattern is better than DAO due its interfaces are closed to modification. 我的结论 - 存储库模式比DAO更好,因为它的接口很难修改。

Am I right so far? 我到目前为止对吗? Haven't I missed some benefits of repository pattern? 我没有错过存储库模式的一些好处吗?

BUT, if you'd look at Spring's accessing data JPA guide , you'll find the next code: 但是,如果您查看Spring访问数据JPA指南 ,您将找到下一个代码:

public interface CustomerRepository extends CrudRepository<Customer, Long> {
    List<Customer> findByLastName(String lastName); //each time you need custom behavior you need to add a method
    //...
}

Doesn't it conflict with the previous article? 它不与前一篇文章冲突吗? Why Spring's repository force us to add new methods to interface? 为什么Spring的存储库强制我们向​​接口添加新方法?

My conslusion - repository pattern is better than DAO due its interfaces are closed to modification 我的结论 - 存储库模式比DAO更好,因为它的接口很难修改

It depends on... 这取决于...
Because repository pattern is more complex since it requires more code to write and has a bigger level of abstraction than DAO pattern for both clients of repository and implementation of it. 因为存储库模式更复杂,因为它需要更多的代码来编写,并且对于存储库的客户端和它的实现具有比DAO模式更大的抽象级别。
When you need to have flexibility in your queries and/or your queries mix multiple entities in the result , repository pattern can address these needs. 当您需要在查询中具有灵活性和/或您的查询在结果中混合多个实体时,存储库模式可以满足这些需求。 If you need to have mainly simple crud operations on a table (basic create, read, update and delete operations), I think that using a real repository (so with specifications) may be an overhead. 如果你需要在表上进行主要简单的crud操作(基本的创建,读取,更新和删除操作),我认为使用真实的存储库(如此使用规范)可能是一个开销。

BUT, if you'd look at Spring's accessing data JPA guide, you'll find the next code: 但是,如果您查看Spring访问数据JPA指南,您将找到下一个代码:

 public interface CustomerRepository extends CrudRepository<Customer,Long> {
    List<Customer> findByLastName(String lastName); //each time you need custom behavior you need to add a method
     //... }

Doesn't it conflict with the previous article? 它不与前一篇文章冲突吗? Why Spring's repository force us to add new methods to interface? 为什么Spring的存储库强制我们向​​接口添加新方法?

Yes. 是。 I think that the problem comes from Spring which uses a fashion term (repository) to stand for a class which is not a repository according to pattern literature. 我认为问题来自于Spring,它使用时尚术语(存储库)来代表根据模式文献而不是存储库的类。 ( http://martinfowler.com/eaaCatalog/repository.html ) http://martinfowler.com/eaaCatalog/repository.html
I think you should consider Spring Repository as DAO since the base functional interface of Spring repository is CrudRepository. 我认为您应该将Spring Repository视为DAO,因为Spring存储库的基本功能接口是CrudRepository。 And by nature CRUD operations are operations we find in a DAO... 从本质上讲,CRUD操作是我们在DAO中发现的操作......

After, nothing prevents you from enriching the repository to provide repository methods with Spring specifications as in the 2.4 point of the official documentation of Spring data . 之后,没有什么可以阻止您丰富存储库以提供Spring规范的存储库方法,如Spring数据的官方文档中的2.4点。
Spring proposes you to extend the org.springframework.data.repository.CrudRepository interface as in your example. Spring建议您像示例一样扩展org.springframework.data.repository.CrudRepository接口。 It is the easier way of doing and I imagine it is the most common way of doing... 这是更容易的做法,我想这是最常见的做法...

public interface CustomerRepository extends CrudRepository<Customer, Long>, JpaSpecificationExecutor {
 …
}

And JpaSpecificationExecutor provides methods which use specifications and therefore promote the reduction of duplicate processings in queries source code : JpaSpecificationExecutor提供了使用规范的方法,因此促进了查询源代码中重复处理的减少:

/*
 * Copyright 2008-2011 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.data.jpa.repository;

import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;

/**
 * Interface to allow execution of {@link Specification}s based on the JPA criteria API.
 * 
 * @author Oliver Gierke
 */
public interface JpaSpecificationExecutor<T> {

    /**
     * Returns a single entity matching the given {@link Specification}.
     * 
     * @param spec
     * @return
     */
    T findOne(Specification<T> spec);

    /**
     * Returns all entities matching the given {@link Specification}.
     * 
     * @param spec
     * @return
     */
    List<T> findAll(Specification<T> spec);

    /**
     * Returns a {@link Page} of entities matching the given {@link Specification}.
     * 
     * @param spec
     * @param pageable
     * @return
     */
    Page<T> findAll(Specification<T> spec, Pageable pageable);

    /**
     * Returns all entities matching the given {@link Specification} and {@link Sort}.
     * 
     * @param spec
     * @param sort
     * @return
     */
    List<T> findAll(Specification<T> spec, Sort sort);

    /**
     * Returns the number of instances that the given {@link Specification} will return.
     * 
     * @param spec the {@link Specification} to count instances for
     * @return the number of instances
     */
    long count(Specification<T> spec);
}

But I think that it will create the Frankenstein creature : half DAO, half repository. 但我认为它会创造出弗兰肯斯坦的生物:半个DAO,半个存储库。

The other solution is implementing directly the base and marker interface : org.springframework.data.repository.Repository and the JpaSpecificationExecutor interface like that : 另一个解决方案是直接实现base和marker接口: org.springframework.data.repository.RepositoryJpaSpecificationExecutor接口,如下所示:

public interface CustomerRepository extends Repository<Customer, Long>, JpaSpecificationExecutor {
 …
}

In this way, you could have a real repository, with only specification methods. 通过这种方式,您可以拥有一个真正的存储库,只使用规范方法。
I don't know if it works. 我不知道它是否有效。 I never tried that. 我从来没有尝试过。

Edit : response to comment 编辑:回复评论

Repository pattern is a concept that Hibernate doesn't provide with an out of box solution. 存储库模式是Hibernate不提供开箱即用解决方案的概念。
But Hibernate and more generally the JPA 2 specification provide indeed Criteria as basic ingredient to create specifications as classes. 但是Hibernate以及更普遍的JPA 2规范确实提供了Criteria作为创建规范作为类的基本要素。
You can then create a custom class which implements the Repository pattern by proposing required methods with specifications as input. 然后,您可以通过提供具有规范作为输入的所需方法来创建实现Repository模式的自定义类。 I think you can use ORM and repositories since you can use ORM with specifications by using criteria API. 我认为您可以使用ORM和存储库,因为您可以使用条件API将ORM与规范一起使用。 Some people oppose ORM and Repository and I disagree. 有些人反对ORM和Repository,我不同意。 ORM is not based on DAO pattern. ORM不是基于DAO模式。 DAO is the way to manipulate data in database. DAO是操纵数据库中数据的方法。 ORM is the way to structure data objects to represent database structures. ORM是构造数据对象以表示数据库结构的方法。 For example, by using both, you can benefit both from the flexibility of specifications and the power of relational-object mapping and of the weaving between entities. 例如,通过使用两者,您可以从规范的灵活性和关系对象映射的功能以及实体之间的编织中获益。
If you don't use ORM or ORM like as IBatis, you should code yourself what ORM offers to you : the object relational mapping. 如果您不像IBatis那样使用ORM或ORM,您应该自己编写ORM为您提供的代码:对象关系映射。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM