当我阅读有关存储库的文档时,通常会与实体和工作组合作。收集,但以“只读”的方式。
从来没有例子存储库包含insertUser(User $user)
或updateUser(User $user)
等方法。
但是,在使用SOA时,Service不应该使用Entity Manager(这是对的,不是吗?)所以:
从这两个问题,另一个问题,我的服务应该明确persist()
& flush()
我的实体?
答案 0 :(得分:39)
是的,存储库通常仅用于查询。
我是这样做的。 service layer管理持久性。控制器层知道服务层,但不知道模型对象是如何持久存在的,也不知道它们来自何处。对于控制器层所关心的是要求服务层持久并返回对象 - 它并不关心它是如何实际完成的。
服务层本身非常适合了解持久层:实体或文档管理器,存储库等。
这里有一些代码可以让它更清晰:
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);
}
}
答案 1 :(得分:3)
如果您查看存储库模式http://martinfowler.com/eaaCatalog/repository.html,
据说存储库使用“类似集合的接口”。
稍后,它还写成“可以从存储库添加和删除对象,因为它们可以从简单的对象集合中添加”。
我不是说这是一本圣经,但从概念上讲,看到像你可以查询的集合这样的存储库并没有错。 但由于它是一个集合,你可以添加,删除,... 实际上,ObjectRepository应该实现Doctrine \ Common \ Collection:)
另一方面,最重要的是不要像读取CQS那样弄乱读写。 这也许就是为什么他们不直接允许这样做,以避免滥用和读/写混合。
编辑:我应该谈谈flush
。这应该在存储库本身不,因为它可能会破坏事务的一致性。
你最好将flush
调用移动到包装整个业务事务逻辑的东西(处理命令f.e的命令总线)?
答案 2 :(得分:1)
那么,在不使用entityManager时如何获取存储库?毕竟,如果没有与数据库的连接,实体将不会神奇地保存,因此您的服务必须以某种方式了解任何类型的连接。
我不了解SOA服务,但在我看来,如果您使用$_em->getRepository()->save($entity)
或$_em->persist($entity)
,则完全没有区别。另一方面,如果在存储库中使用flush,则最终可能会遇到比所需更多的查询,因为您的存储库现在已经了解了业务逻辑。
我认为有一种方法可以做到这一点" SOA方式",但我想它并没有在存储库中持久保存实体。