Doctrine2存储库是保存实体的好地方吗?

Tre*_*ent 53 soa design-patterns service-layer symfony doctrine-orm

当我阅读有关存储库的文档时,通常使用实体和集合,但是以"只读"的方式.

从来没有存储库具有类似insertUser(User $user)或的方法的示例updateUser(User $user).

但是,在使用SOA时,Service不应该使用Entity Manager(这是对的,不是吗?)所以:

  1. 我的服务应该知道全局EntityManager吗?
  2. 我的服务应该只知道使用过的存储库(比方说,UserRepository和ArticleRepository)

从这两个问题,另一个问题,我的服务应该明确persist()flush()我的实体吗?

Eln*_*mov 42

是的,存储库通常仅用于查询.

我就是这样做的.该服务层管理的持久性.控制器层知道服务层,但不知道模型对象是如何持久存在的,也不知道它们来自何处.对于控制器层关心的是要求服务层保持并返回对象 - 它并不关心它是如何实际完成的.

服务层本身非常适合了解持久层:实体或文档管理器,存储库等.

这里有一些代码可以让它更清晰:

class UserController
{
    public function indexAction()
    {
        $users = $this->get('user.service')->findAll();
        // ...
    }

    public function createAction()
    {
        // ...
        $user = new User();
        // fill the user object here
        $this->get('user.service')->create($user);
        // ...
    }
}

class UserService
{
    const ENTITY_NAME = 'UserBundle:User';

    private $em;

    public function __construct(EntityManager $em)
    {
        $this->em = $em;
    }

    public function findAll()
    {
        return $this->em->getRepository(self::ENTITY_NAME)->findAll();
    }

    public function create(User $user)
    {
        // possibly validation here

        $this->em->persist($user);
        $this->em->flush($user);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 持久的控制器层感觉不对,因为控制器应该只使用GUI,即它们只是解析请求,将所有"真实"工作委托给服务层,并返回响应.大多数时候我每个实体/文档都有一个服务,但这不是一个规则,因为有时你可以拥有没有实体的服务,理论上(我还没有)管理多个实体的服务. (11认同)

Flo*_*ian 7

如果您查看存储库模式http://martinfowler.com/eaaCatalog/repository.html

据说存储库使用“类似集合的界面”。

后来,它也写成“对象可以从存储库中添加和删除,就像它们可以从一个简单的对象集合中一样”。

我并不是说这是一本圣经,但从概念上讲,将存储库视为您可以查询的集合并没有错。但是因为它是一个集合,所以你可以添加、删除、......事实上,ObjectRepository 应该实现 Doctrine\Common\Collection :)

另一方面,正如 CQS 所说,最重要的是不要将读取和写入搞得一团糟。这可能就是为什么他们不允许直接这样做,以避免滥用和读/写混合。

编辑:我应该谈论flush. 这应该在存储库本身中进行,因为它可能会破坏事务一致性。

您最好将flush调用移动到包装整个业务事务逻辑的东西(处理命令 fe 的命令总线?)