mysql - 原则 2 和垂直划分

标签 mysql entity-framework symfony doctrine-orm vertical-partitioning

我目前正在开发一个项目,我必须处理很多用户字段(+/- 80)。我的第一个方法是(现在仍然是)将用户表垂直划分为 4 个表:主要信息、管理信息、银行信息、统计信息。 3个额外表行的id引用主表的自动递增id。

我的问题是:

  1. 这样做有意义吗?
  2. 看起来,按照我的做法 关联,Doctrine 无法将一个对象刷新到数据库中 一举两得:

Entity of type MyVendor\User\UserBundle\Entity\UsersInfosBank is missing an assigned ID for field 'id_user'. The identifier generation strategy for this entity requires the ID field to be populated before EntityManager#persist() is called. If you want automatically generated identifiers instead you need to adjust the metadata mapping accordingly.

该项目将在三周内投入生产,因此我们仍然可以回到更传统的方式将这些数据存储到一个巨大的表中......

****************更新********************

下面的完整代码逻辑********************

<小时/>

我刚刚删除了大部分与我的问题无关的属性和方法......

是的,我正在使用 FOSUserBundle ;)

用户主

<?php

namespace LCP\User\UserBundle\Entity;

use FOS\UserBundle\Model\GroupableInterface;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;

/**
 * UsersMain
 *
 * @ORM\Table(name="lcp_users_main")
 * @ORM\Entity
 */
class UsersMain extends BaseUser 
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;


    /**
     *
     * @ORM\OneToOne(targetEntity="LCP\User\UserBundle\Entity\UsersInfosBank", mappedBy="id_user", cascade={"persist"})
     */
    private $infosBank;

    /**
     *
     * @ORM\OneToOne(targetEntity="LCP\User\UserBundle\Entity\UsersApodis", mappedBy="id_user", cascade={"persist"})
     */
    private $apodis;

    /**
     *
     * @ORM\OneToOne(targetEntity="LCP\User\UserBundle\Entity\UsersInfosAdmin", mappedBy="id_user", cascade={"persist"})
     */
    private $infosAdmin;

    /**
     *
     * @ORM\OneToOne(targetEntity="LCP\User\UserBundle\Entity\UsersInfosStats", mappedBy="id_user", cascade={"persist"})
     */
    private $infosStats;



    /**
     * Constructor
     */
    public function __construct()
    {
        $this->groups = new \Doctrine\Common\Collections\ArrayCollection();
        $this->creationDate = new \Datetime();
    }

    /**
     * Set apodis
     *
     * @param \LCP\User\UserBundle\Entity\UsersApodis $apodis
     * @return UsersMain
     */
    public function setApodis(\LCP\User\UserBundle\Entity\UsersApodis $apodis = null)
    {
        if(is_null($this->apodis) && is_null($apodis)){
            $this->apodis = new \LCP\User\UserBundle\Entity\UsersApodis();
        } else {
            $this->apodis = $infosBank;
        }

        $this->apodis->setIdUser($this);

        return $this;
    }

    /**
     * Get apodis
     *
     * @return \LCP\User\UserBundle\Entity\UsersApodis 
     */
    public function getApodis()
    {
        if(is_null($this->infosAdmin)){
            $this->infosAdmin = new \LCP\User\UserBundle\Entity\UsersApodis();
        }
        return $this->apodis;
    }

    /**
     * Set infosAdmin
     *
     * @param \LCP\User\UserBundle\Entity\UsersInfosAdmin $infosAdmin
     * @return UsersMain
     */
    public function setInfosAdmin(\LCP\User\UserBundle\Entity\UsersInfosAdmin $infosAdmin = null)
    {
        if(is_null($this->infosAdmin) && is_null($infosAdmin)){
            $this->infosAdmin = new \LCP\User\UserBundle\Entity\UsersInfosAdmin();
        } else {
            $this->infosAdmin = $infosAdmin;
        }

        $this->infosAdmin->setIdUser($this);

        return $this;
    }

    /**
     * Get infosAdmin
     *
     * @return \LCP\User\UserBundle\Entity\UsersInfosAdmin 
     */
    public function getInfosAdmin()
    {
        if(is_null($this->infosAdmin)){
            $this->infosAdmin = new \LCP\User\UserBundle\Entity\UsersInfosAdmin();
        }
        return $this->infosAdmin;
    }

    /**
     * Set infosStats
     *
     * @param \LCP\User\UserBundle\Entity\UsersInfosStats $infosStats
     * @return UsersMain
     */
    public function setInfosStats(\LCP\User\UserBundle\Entity\UsersInfosStats $infosStats = null)
    {
        if(is_null($this->infosStats) && is_null($infosStats)){
            $this->infosStats = new \LCP\User\UserBundle\Entity\UsersInfosStats();
        } else {
            $this->infosStats = $infosAdmin;
        }

        $this->infosStats->setIdUser($this);

        return $this;
    }

    /**
     * Get infosStats
     *
     * @return \LCP\User\UserBundle\Entity\UsersInfosStats 
     */
    public function getInfosStats()
    {
        if(is_null($this->infosStats)){
            $this->infosStats = new \LCP\User\UserBundle\Entity\UsersInfosStats();
        }
        return $this->infosStats;
    }



}

UsersInfosAdmin

<?php

namespace LCP\User\UserBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * UsersInfosAdmin
 *
 * @ORM\Table(name="lcp_users_infos_admin", indexes={@ORM\Index(name="pharmacyCip_idx", columns={"pharmacy_cip"})})
 * @ORM\Entity
 */
class UsersInfosAdmin
{

    /**
     * @var integer
     * @ORM\Id
     * @ORM\OneToOne(targetEntity="LCP\User\UserBundle\Entity\UsersMain", cascade={"persist"}, inversedBy="infosAdmin")
     */
    private $id_user;


    /**
     * Set id_user
     *
     * @param \LCP\User\UserBundle\Entity\UsersMain $idUser
     * @return UsersInfosAdmin
     */
    public function setIdUser(\LCP\User\UserBundle\Entity\UsersMain $idUser)
    {
        $this->id_user = $idUser;

        return $this;
    }

    /**
     * Get id_user
     *
     * @return \LCP\User\UserBundle\Entity\UsersMain 
     */
    public function getIdUser()
    {
        return $this->id_user;
    }
}

用户信息统计

<?php

namespace LCP\User\UserBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * UsersInfosStats
 *
 * @ORM\Table(name="lcp_users_infos_stats")
 * @ORM\Entity
 */
class UsersInfosStats
{
    /**
     * @var integer
     * @ORM\Id
     * @ORM\OneToOne(targetEntity="LCP\User\UserBundle\Entity\UsersMain", cascade={"persist"}, inversedBy="infosStats")
     */
    private $id_user;

    /**
     * Set id_user
     *
     * @param \LCP\User\UserBundle\Entity\UsersMain $idUser
     * @return UsersInfosStats
     */
    public function setIdUser(\LCP\User\UserBundle\Entity\UsersMain $idUser)
    {
        $this->id_user = $idUser;

        return $this;
    }

    /**
     * Get id_user
     *
     * @return \LCP\User\UserBundle\Entity\UsersMain 
     */
    public function getIdUser()
    {
        return $this->id_user;
    }
}

这是我创建用户的方法(通过安全管理区域表单):

/**
* This action get the field from the form
*/
public function userSaveAction(Request $request)
{
    $userManager = $this->get('fos_user.user_manager');
    $this->request = $request;
    $userValues = $this->getRequest()->request->all();
    $this->em = $this->getDoctrine()->getManager();

    $user = $this->processUser($userValues);

    $userManager->updateUser($user, false);

    return $this->redirect($this->generateUrl('lcp_admin_user_edit', ['id'=>$user->getId()]));
}

/**
* This method process user fields and uses setters (or getters for joined entities) to set datas of user
*/
private function processUser($userValues)
{
    if($userValues['userId']=="") {
        $user = $this->get('fos_user.user_manager')->createUser();
    } else {
        $user = $this->em->getRepository('LCPUserBundle:UsersMain')
                ->findOneBy(['id' => $userId]);
    }

    //construction of related entities
    $user->setInfosAdmin();
    $user->setInfosBank();
    $user->setInfosStats();
    $user->setApodis();

    unset($userValues['userId']);

    //this method inspect submitted field to check if they are mandatory or if current user is allowed to modify them
    $this->fields = $this->getInfosFields();

    foreach($userValues as $input=>$value){
        list($entity,$input)=explode('-',$input);
        if($input=='plainPassword' && $value==''){
            continue;
        }
        if($entity=='Main'){
            $setter = 'set'.ucfirst($input);
            $user->$setter($value);
        } else {
            $setter = 'set'.ucfirst($input);
            $join = 'get'.$entity;

            $user->$join()->$setter($value);
        }
    }
    return $user;
}

最佳答案

根据评论,您的 UsersMain 属性需要如下所示:

/**
 * Join administrative informations
 * @ORM\OneToOne(targetEntity="MyVendor\User\UserBundle\Entity\UsersInfosAdmin", mappedBy="userMain", cascade={"persist"}, orphanRemoval=true)
 */
private $infosAdmin;

/**
 * Setter InfosAdmin
 */
public function setInfosAdmin(UsersInfosAdmin $infosAdmin)
{
    $this->infosAdmin = $infosAdmin;
    $this->infosAdmin->setUserMain($this); <--- add this to set userMain on associated object

    return $this;
}

那么您的UsersInfosAdmin属性需要如下所示:

/**
 * @var integer
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
 private $id;

/**
 * @ORM\OneToOne(targetEntity="MyVendor\User\UserBundle\Entity\UsersMain", inversedBy="userMain")
 */
 private $userMain;

关于mysql - 原则 2 和垂直划分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27396405/

相关文章:

php - 覆盖 symfony radio 部件

mysql - 将 2 个 sql 查询合并为一个

mysql - 从表 B 中获取与表 A 中的多个条目(给定列表)相关的所有条目

c# - 如何从linq中的多个日期列中获取最小值?

c# - 在代码优先 Entity Framework 中将 DbContext 转换为数据表

php - Symfony2 密码重置而不覆盖 FOSUser

mysql - 在 OrderBy Doctrine Querybuilder 中使用 IS NULL 和 COALESCE

php - 将表的内容保存到变量中

php - Codeigniter - 模型 - 重复输入警报

c# - 为什么 EntityState 枚举是用 FlagsAttribute 定义的