我有两个实体
EntityA:
id: ~
name: ~
EntityB:
id: ~
name: ~
entityA: ~
unique: [entityA, name]
当我提交新的EntityB时,我有大约10000个实体EntityA
curl -X POST http://localhost/api/entityb.json -d {name: "Hello World", entityA: "017cbc11-95be-4280-8093-9e5b641d73a5"}
我的商务逻辑非常简单
protected function process(array $parameters, EntityB $object, EntityBType $type, $method = 'PUT')
{
$form = $this->getFormfactory()->create($type, $object);
$form->submit($parameters, 'PATCH' !== $method);
if ($form->isValid()) {
$this->getEm()->persist($object);
$this->getEm()->flush();
//... returns 201
}
// return 400
}
EntityB FormType
class EntityBType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('id')
->add('name')
->add('entityA', null, array(
'property' => 'id'
))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'ApplicationBundle\Entity\EntityB'
));
}
/**
* {@inheriDoc}
*/
public function getName()
{
return '';
}
}
EntityB
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\Table;
use Doctrine\ORM\Mapping\UniqueConstraint;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints\NotNull;
/**
* Class EntityB
* @package ApplicationBundle\Entity\EntityB
* @Entity()
* @Table(
* name="entity_b",
* uniqueConstraints={
* @UniqueConstraint(name="entity_b_uniq", columns={"entity_a_id", "name"})
* }
* )
* @UniqueEntity(fields={"entityA", "name"})
*/
class EntityB {
/**
* @var string
* @Id()
* @GeneratedValue(strategy="UUID")
* @Column(name="id", length=36)
*/
protected $id;
/**
* @var string
* @Column(name="name", length=250)
* @NotNull()
*/
protected $name;
/**
* @var EntityA
* @ManyToOne(targetEntity="ApplicationBundle\Entity\EntityA")
*/
protected $entityA;
// setter and getters ...
}
采取aprox。 2300ms这太多了!在我的开发环境中,保存aprox是300ms。我认为这里的问题是当我使用从数据库中获取所有EntityA的形式验证eht entityB时,我怎么能解决这个问题?我正在开发的系统需要50000到100000个EntityBs
时间:14.40 ms
SELECT
t0.id AS id1,
t0.name AS name4
FROM
entityA t0
时间:0.64毫秒
SELECT
t0.id AS id1,
t0.name AS name2,
t0.entity_a_id AS entity_a_id3
FROM
entity_b t0
WHERE
t0.entity_a_id = ?
AND t0.name = ?
Parameters: [017cbc11-95be-4280-8093-9e5b641d73a5, 'Hello World']
时间0.28毫秒
SELECT UUID()
时间0.23毫秒
START TRANSACTION
时间:0.49毫秒
INSERT INTO entity_b (id, name, entity_a_id)
VALUES
(?, ?, ?)
Parameters: { 1: fb2dd6c9-3989-11e4-a5d6-1867b083cd22, 2: 'Hello World!', 3: 017cbc11-95be-4280-8093-9e5b641d73a5 }
时间:240.54毫秒
COMMIT
这让我觉得问题是因为当你得到EntityA的列表时,因为控制器中的时间线显示我2318ms(doctrine使用了289ms),这里的问题可能是表单验证器组件
答案 0 :(得分:1)
所以我要在这里进行一次飞跃并猜测:
class EntityBType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('id')
->add('name')
->add('entityB', null, array(
'property' => 'id'
))
;
}
实际上是这样的:
class EntityBType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('entityA', 'entity', array(
'class' => 'EntityA',
'property' => 'id'
))
;
}
设置type = entity实际上会默认加载整个EntityA表,这解释了性能问题。当人们发布他们认为代码应该是什么样的内容而不是实际内容时,我总是笑一笑。
要取消默认查询,请按以下步骤操作:http://symfony.com/doc/current/reference/forms/types/entity.html#using-choices
由于您已经拥有EntityA id,只需查询它,然后将其作为choices参数传递。我不会尝试为您提供准确的代码,因为您的问题中的内容与您的实际代码不符,因此浪费时间。
但这应该让你去。
答案 1 :(得分:0)
doctrine manager实际上并不是设计用于处理超过1000个实体同时保存...
优化它的好处是刷新每500或1000个实体,然后清除学说管理器或最终重新创建你的学说管理器对象。
// your loop through object to save
$a = 0;
foreach ( $dataCollection as $data )
{
$newB = new entityB();
///// settings for entityB
$entityManager->persist( $newB );
$a++;
// we reached 1000 entitiesB so we flush and clear
if ( $a%1000 == 0 )
{
$entityManager->flush();
$entityManager->clear(); // we clean our entity manager queue
}
}