Doctrine2批量导入尝试与另一个实体一起工作 [英] Doctrine2 bulk import try to work with another entity

查看:219
本文介绍了Doctrine2批量导入尝试与另一个实体一起工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一个成员导入批次(带有插入和更新)的大型项目与许多实体,如成员客户 ...



在Doctrine doc中阅读了有关批量导入的章节后,我实现了以下代码:



pre> $ batchSize = 20;
$ i = 0;

foreach($ entities as $ entity)
{
$ this-> getEntityManager() - > persist($ entity);

if(($ i%$ batchSize)=== 0)
{
$ this-> getEntityManager() - > flush();
$ this-> getEntityManager() - > clear();
}
}

$ this-> getEntityManager() - > flush();
$ this-> getEntityManager() - > clear();

现在,当我想批量处理一个成员数组实体,Doctrine尝试将空数据插入与实体相关的完整其他表,并抛出异常发生异常执行'INSERT INTO组...



成员之间没有任何关系 ...



任何关于这个奇怪行为的想法?



编辑



简短地图细节:

  ** 
* @ ORM\Entity
* @ ORM\Table(name =members)
* /
class Member
{
//一些属性...

/ **
* @ ORM\ManyToOne(targetEntity =Client,inversedBy =members,cascade = {persist,merge })
* @ ORM\JoinColumn(name =client_id,referencedColumnName =id,onDelete =CASCADE)
* /
protected $ client;

/ **
* @return客户端
* /
public function getClient()
{
return $ this-> client ;
}

/ **
* @param客户端$客户端
*
* @return $ this
* /
public function setClient(Client $ client)
{
$ this-> client = $ client;

return $ this;
}
}

/ **
* @ ORM\Entity
* @ ORM\Table(name =clients)
* /
class Client
{
/ **
* @ ORM\OneToMany(targetEntity =Member,mappedBy =client,cascade = {persist ,remove,merge},fetch =EXTRA_LAZY)
* /
protected $ members;

/ **
* @ ORM\ManyToOne(targetEntity =Group,inversedBy =clients,cascade = {persist,merge})
* @ ORM\JoinColumn(name =clients_id,referencedColumnName =id,onDelete =SET NULL)
* /
protected $ group;

public function __construct()
{
$ this-> members = new ArrayCollection();
}

/ **
* @return ArrayCollection
* /
public function getMembers()
{
return $这 - >成员;
}

/ **
* @param $ members
*
* @return $ this
* /
public函数setMembers($ members)
{
$ this-> members = new ArrayCollection();

return $ this-> addMembers($ members);
}

/ **
* @param $ members
*
* @return $ this
* /
public函数addMembers($ members)
{
foreach($ members as $ member)
{
$ this-> addMember($ member);
}

return $ this;
}

/ **
* @param会员$会员
*
* @return $ this
* /
public function addMember(member $ member)
{
$ this-> members-> add($ member);
$ member-> setClient($ this);

return $ this;
}

/ **
* @param会员$会员
*
* @return $ this
* /
public function removeMember(member $ member)
{
if($ this-> members-> contains($ member))
{
$ this-> > removeElement($构件);
}

return $ this;
}

/ **
* @param $ members
*
* @return $ this
* /
public函数removeMembers($ members)
{
foreach($ members as $ member)
{
$ this-> removeMember($ member);
}

return $ this;
}

/ **
* @param组$ group
*
* @return $ this
* /
public function setGroup(Group $ group = null)
{
$ this-> group = $ group;

return $ this;
}

/ **
* @return组
* /
public function getGroup()
{
return $这 - 基团;
}
}

/ **
* @ ORM\Entity
* @ ORM\Table(name =groups)
* /
class Group
{
/ **
* @ ORM\OneToMany(targetEntity =Client,mappedBy =group)
* /
protected $ clients;

public function __construct()
{
$ this-> clients = new ArrayCollection();
}

/ **
* @return ArrayCollection
* /
public function getClients()
{
return $这 - >客户端;
}

/ **
* @param $ clients
*
* @return $ this
* /
public函数setClients($ clients)
{
$ this-> clients = new ArrayCollection();

return $ this-> addClients($ clients);
}

/ **
* @param $ clients
*
* @return $ this
* /
public函数addClients($ clients)
{
foreach($ clients as $ client)
{
$ this-> addClient($ client);
}

return $ this;
}

/ **
* @param客户端$客户端
*
* @return $ this
* /
public function addClient(Client $ client)
{
if(!$ this-> clients->包含($ client))
{
$ this->客户端 - >添加($客户端);
$ client-> setGroup($ this);
}

return $ this;
}

/ **
* @param $ clients
*
* @return $ this
* /
public函数removeClients($ clients)
{
foreach($ clients as $ client)
{
$ this-> removeClient($ client);
}

return $ this;
}

/ **
* @param客户端$客户端
*
* @return $ this
* /
public function removeClient(Client $ client)
{
if($ this-> clients-> contains($ client))
{
$ this-> clients- > removeElement($客户端);
$ client-> setGroup(null);
}

return $ this;
}
}

错误类型为:



执行INSERT INTO组时发生异常SQLSTATE [23502]:不为空违规:7错误:列标签中的空值不违反-null constraint
详细信息:未完成的行包含(60,null,f,null,f,null,null)。



< EDIT2



这是表创建描述(使用postgresql):

  CREATE TABLE组(
id integer NOT NULL,
tempref character vary(255)DEFAULT NULL :: character varying,
prorated_basis boolean NOT NULL,
fixed_price_amount double precision,
is_indexed boolean,
pricing_grid pricing [],
标签字符变化(255)NOT NULL
);

CREATE SEQUENCE组
START WITH 1
增加1
无MINVALUE
无MAXVALUE
CACHE 1;

ALTER SEQUENCE groups_id_seq OWNED BY groups.id;

ALTER TABLE ONLY pricing_groups ALTER COLUMN id SET DEFAULT nextval('groups_id_seq':: regclass);

ALTER TABLE ONLY组
ADD CONSTRAINT groups_pkey PRIMARY KEY(id);


解决方案

我可以描述造成错误的原因,猜测为什么会造成这种情况,并在调试时提供一些提示。



正如您所述,您正在更新作为客户端一部分的成员,而这些成员又是组的一部分。正如您在 cascade = persist 上的关系中指定的那样,持久化成员时,客户端和组也被保存。这意味着,在插入成员时,组将被更新或创建。在您的情况下,您将通过此机制创建一个新组。但是,该组没有标签属性集,导致数据库中的 NULL 值不允许通过计划。



正如你所说,这个错误已经在最好的批次中发生了。您更新隐含的前20名成员之一创建一个没有标签的新组。要找出哪一个,我建议使用调试器,并在持久化之前检查每个成员,以查看该成员的组成部分,以及数据库中是否存在。如果不存在(通过 ID ),您应该调查为什么此组不需要标签集。



如果所有组实际上都存在于数据库中,事情会变得更棘手,这取决于如何加载更新的成员。是从EntityManager(管理状态)中获取的,还是从某些不同的源(例如序列化)中加载,因此在非管理状态?如果它们不受管理,它们将变得管理,并且通过规定关系 cascade = merge ,客户端和组也将被管理。这里有一个重要的事情要知道, merge 将返回一个新的(被管理的)实体,然后被持久化(参见接受的答案这里)。由于这是一个新对象,所以可能是这个对象没有被完全初始化,并且可能包含未定义的值(然后将转换为 NULL )。
所以当从与EntityManager不同的源加载成员数据时,您可能必须先连接到EntityManager以避免此问题。



调试最后一个是相当困难的,您需要进入 UnitOfWork-> doPersist 方法看看每个实体是如何实际坚持的。


I'm working on a members import batch (with insertions and updates) for a big project with a lot of entities such as Member, Client, Group, ....

After reading the chapter related to bulk imports in Doctrine doc, I've implemented this code :

$batchSize = 20;
$i         = 0;

foreach ($entities as $entity)
{
    $this->getEntityManager()->persist($entity);

    if (($i % $batchSize) === 0)
    {
        $this->getEntityManager()->flush();
        $this->getEntityManager()->clear();
    }
}

$this->getEntityManager()->flush();
$this->getEntityManager()->clear();

Now, when I want to bulk handle an array of Member entities, Doctrine try to insert null data into a completely other table related to the Group entity and an exception is thrown An exception occurred while executing 'INSERT INTO groups ...

There are not any relations between Member and Group ...

Any idea about this weird behavior ?

EDIT

Short mapping details :

/**
 * @ORM\Entity
 * @ORM\Table(name="members")
 */
class Member
{
    // some properties ...

    /**
     * @ORM\ManyToOne(targetEntity="Client", inversedBy="members", cascade={"persist", "merge"})
     * @ORM\JoinColumn(name="client_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $client;

    /**
     * @return Client
     */
    public function getClient()
    {
        return $this->client;
    }

    /**
     * @param Client $client
     *
     * @return $this
     */
    public function setClient(Client $client)
    {
        $this->client = $client;

        return $this;
    }
}

/**
 * @ORM\Entity
 * @ORM\Table(name="clients")
 */
class Client
{
    /**
     * @ORM\OneToMany(targetEntity="Member", mappedBy="client", cascade={"persist", "remove", "merge"}, fetch="EXTRA_LAZY")
     */
    protected $members;

    /**
     * @ORM\ManyToOne(targetEntity="Group", inversedBy="clients", cascade={"persist", "merge"})
     * @ORM\JoinColumn(name="clients_id", referencedColumnName="id", onDelete="SET NULL")
     */
    protected $group;

    public function __construct()
    {
        $this->members = new ArrayCollection();
    }

    /**
     * @return ArrayCollection
     */
    public function getMembers()
    {
        return $this->members;
    }

    /**
     * @param $members
     *
     * @return $this
     */
    public function setMembers($members)
    {
        $this->members = new ArrayCollection();

        return $this->addMembers($members);
    }

    /**
     * @param $members
     *
     * @return $this
     */
    public function addMembers($members)
    {
        foreach ($members as $member)
        {
            $this->addMember($member);
        }

        return $this;
    }

    /**
     * @param Member $member
     *
     * @return $this
     */
    public function addMember(Member $member)
    {
        $this->members->add($member);
        $member->setClient($this);

        return $this;
    }

    /**
     * @param Member $member
     *
     * @return $this
     */
    public function removeMember(Member $member)
    {
        if ($this->members->contains($member))
        {
            $this->members->removeElement($member);
        }

        return $this;
    }

    /**
     * @param $members
     *
     * @return $this
     */
    public function removeMembers($members)
    {
        foreach ($members as $member)
        {
            $this->removeMember($member);
        }

        return $this;
    }

    /**
     * @param Group $group
     *
     * @return $this
     */
    public function setGroup(Group $group = null)
    {
        $this->group = $group;

        return $this;
    }

    /**
     * @return Group
     */
    public function getGroup()
    {
        return $this->group;
    }
}

/**
 * @ORM\Entity
 * @ORM\Table(name="groups")
 */
class Group
{
    /**
     * @ORM\OneToMany(targetEntity="Client", mappedBy="group")
     */
    protected $clients;

    public function __construct()
    {
        $this->clients = new ArrayCollection();
    }

    /**
     * @return ArrayCollection
     */
    public function getClients()
    {
        return $this->clients;
    }

    /**
     * @param $clients
     *
     * @return $this
     */
    public function setClients($clients)
    {
        $this->clients = new ArrayCollection();

        return $this->addClients($clients);
    }

    /**
     * @param $clients
     *
     * @return $this
     */
    public function addClients($clients)
    {
        foreach ($clients as $client)
        {
            $this->addClient($client);
        }

        return $this;
    }

    /**
     * @param Client $client
     *
     * @return $this
     */
    public function addClient(Client $client)
    {
        if (!$this->clients->contains($client))
        {
            $this->clients->add($client);
            $client->setGroup($this);
        }

        return $this;
    }

    /**
     * @param $clients
     *
     * @return $this
     */
    public function removeClients($clients)
    {
        foreach ($clients as $client)
        {
            $this->removeClient($client);
        }

        return $this;
    }

    /**
     * @param Client $client
     *
     * @return $this
     */
    public function removeClient(Client $client)
    {
        if ($this->clients->contains($client))
        {
            $this->clients->removeElement($client);
            $client->setGroup(null);
        }

        return $this;
    }
}

And the error is type of :

An exception occurred while executing 'INSERT INTO groups ... SQLSTATE[23502]: Not null violation: 7 ERROR: null value in column "label" violates not-null constraint DETAIL: Failing row contains (60, null, f, null, f, null, null).

EDIT2

This is the table creation description (using postgresql) :

CREATE TABLE groups (
    id integer NOT NULL,
    tempref character varying(255) DEFAULT NULL::character varying,
    prorated_basis boolean NOT NULL,
    fixed_price_amount double precision,
    is_indexed boolean,
    pricing_grid pricing[],
    label character varying(255) NOT NULL
);

CREATE SEQUENCE groups
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;

ALTER SEQUENCE groups_id_seq OWNED BY groups.id;

ALTER TABLE ONLY pricing_groups ALTER COLUMN id SET DEFAULT nextval('groups_id_seq'::regclass);

ALTER TABLE ONLY groups
    ADD CONSTRAINT groups_pkey PRIMARY KEY (id);

解决方案

I can describe what is causing the error, but only guess why it is caused and give some hints on what to look for when debuging this.

As you described, you are updating members, that are part of a client, that in turn is part of a group. As you specified on the relations by cascade=persist, clients and groups are saved as well when persisting a member. That means, groups are either updated or created when inserting members. In your case, you are creating a new group by this mechanism. Yet this group does not have the label property set, resulting in a NULL value in the database, which is not allowed by the scheme.

As you said, this error is already occuring during the best batch. One of the first 20 members you update implicity creates a new group with no label. To find out which one it is I'd suggest using a debugger and inspecet each member before persistence to see what the group of this member is part of, and if it exists in the database. If it does not exist (by ID), you should investigate why this group does not the required label set.

If all groups actually do exist in the database already, things do get a bit more tricky and this depends on how the members you are updating are loaded. Are they fetched from the EntityManager (managed state) or are they loaded from some different source (e.g. serialized) and hence in a unmanaged state? If they are unmanaged, they will become manage upon peristence, and by specification of the relation cascade=merge, client, and group, will become managed as well. There is an important thing to know here though, merge will return a new (managed) entity which is then persisted (see the accepted answer here). As this is a new object, there might be the chance that this object is not fully initialized and can contain undefined values (which then would translate to NULL). So when loading the member data from a different source than the EntityManager, you might have to connect them with the EntityManager first to avoid this problem.

Debugging the last one is quite difficult and you'd need to step into the UnitOfWork->doPersist method to see how each individual entity is actual persisted.

这篇关于Doctrine2批量导入尝试与另一个实体一起工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆