我的应用程序有一个名为“client”的实体,它被注入每个请求对象。
为了提高性能,我设置了一个自定义缓存,并使用JMSSerializer来序列化和缓存客户端对象。当请求进入时,缓存返回序列化的Client对象,JMS对其进行反序列化。
我的应用程序创建其他实体,称之为ChildEntities,并通过ChildEntity上的ManyToOne关系将它们与Client对象关联。
这很好用,直到我开始通过反序列化缓存数据来加载这些对象,而不是使用Doctrine从MySQL数据库加载它们。 Doctrine现在抛出了这个错误:
通过“\ acme \ bundle \ Entity \ ChildEntity#client”关系找到了一个新实体,该关系未配置为对实体进行级联持久操作:ClientName。要解决此问题:在此未知实体上显式调用EntityManager#persist()或在映射中配置级联持久保存此关联,例如@ManyToOne(..,cascade = {“persist”})
所以,如果我正确地理解了这个错误,似乎Doctrine认为我的Client对象是由ChildEntity对象上的ManyToOne关系引用的,是 new 对象(即使我是用它需要保存的ID来反序列化它,但不会因为没有设置级联而停止。
我反对反序列化对象的策略是错误的吗?有没有办法将它们反序列化为代理对象,或者解决此问题的其他方法?我更喜欢将自定义缓存用于教义缓存。
答案 0 :(得分:3)
当我最终找到合适的搜索短语时想出这个。
我使用的是默认对象构造函数,我需要使用Doctrine对象构造函数。
为此,我将此添加到我的services.yml:
jms_serializer.object_constructor:
alias: jms_serializer.doctrine_object_constructor
public: false
答案 1 :(得分:1)
我也使用这个模块,并以json格式保存序列化的教义实体。
所以,我发现我必须配置Spea / JMSSerializerModule来使用DoctrineObjectConstructor而不是UnserializeObjectConstructor。
但是,与UnserializeObjectConstructor相反,DoctrineObjectConstructor不是一个简单的可调用类。构造函数需要两个对象:
问题在于没有接口ManagerRegistry的实现,显然,它没有工厂。
我通过在composer.json中添加此依赖项https://github.com/eddiejaoude/zf2-doctrine2-manager-registry-service来解决此问题。此模块通过服务管理器条目 Doctrine \ ManagerRegistry 提供接口ManagerRegistry的实现。
安装完成后,我为DoctrineObjectConstructor创建了一个工厂:
<?php
namespace Example\Service;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use JMS\Serializer\Construction\DoctrineObjectConstructor;
class DoctrineObjectConstructorFactory implements FactoryInterface
{
/* (non-PHPdoc)
* @see \Zend\ServiceManager\FactoryInterface::createService()
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$serv1 = $serviceLocator->get('Doctrine\ManagerRegistry');
$serv2 = $serviceLocator->get('jms_serializer.unserialize_object_constructor');
$service = new DoctrineObjectConstructor($serv1, $serv2);
return $service;
}
}
并在我的module.config.php中添加了这些条目:
'service_manager' => array(
'factories' => array(
'jms_serializer.doctrine_object_constructor' => 'Example\Service\DoctrineObjectConstructorFactory'
),
'aliases' => array(
'jms_serializer.object_constructor' => 'jms_serializer.doctrine_object_constructor'
),
),
就是这样。现在,它有效。
我在这里写了一个问题:https://github.com/Spea/JMSSerializerModule/issues/12因为我认为我们不应该添加外部模块来执行此操作。