主键和外键同时具有主义2

时间:2011-06-17 09:42:16

标签: php orm foreign-keys primary-key doctrine-orm

我有两张桌子:

A id 作为主键

B id 作为主键和外键

简短说明:

我需要在表格 B 中设置一个主键,该主键也是指向表 A 主键的外键。

有人可以解释我如何通过Doctrine 2中的注释来映射这个吗?

注意:

我试过了这个:

   class A
{
    /**
     * @var bigint $id
     *
     * @Column(name="id", type="bigint", nullable=false)
     * @Id
     * @GeneratedValue(strategy="IDENTITY")
     */
    private $a_id;
...

B 表:


class B
{
    /**
     * @var bigint $id
     * @Id 
     * @OneToOne(targetEntity="A", fetch="LAZY")
     * @JoinColumn(name="id", referencedColumnName="id")
     */
    private $b_id;
...

但它给了我这个错误:

  

未捕获的异常   '学说\ ORM \映射\ MappingException'   消息'无标识符/主要消息   为实体'B'指定的密钥。一切   实体必须具有标识符/主要内容   键。'在   /var/www/agr-reg-php/Doctrine/ORM/Mapping/MappingException.php:37   堆栈跟踪:

N.B:我不能拥有复合主键。

5 个答案:

答案 0 :(得分:11)

这可以从Doctrine 2.1

开始
  

通过外国实体或派生实体进行身份验证:您现在可以使用外键作为实体的标识符。这转换为在@ManyToOne或@OneToOne关联上使用@Id。您可以阅读feature in the tutorial

答案 1 :(得分:2)

我可以解决问题,创建一个与外地相同名称的pk字段

class B
{
/**
 * @var bigint $a_id
 * @Id @Column(name="a_id", type="bigint", nullable="false")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 */
private $a_id;

/**
 * @OneToOne(targetEntity="A", fetch="LAZY")
 * @JoinColumn(name="id", referencedColumnName="id")
 */
private $a;
.
.
.
/**
 * @var A
 *
 * @ORM\OneToOne(targetEntity="A")
 * @ORM\JoinColumns({
 *   @ORM\JoinColumn(name="a_id", referencedColumnName="id", unique=true)
 * })
 */
private $a;
//...

答案 2 :(得分:1)

最后,我通过在实体类中为真实表中的同一列指定两个字段来解决我的问题。这些更改仅在B类中进行(查看A类的问题):


class B
{
    /**
     * @var bigint $id
     * @Id @Column(name="id", type="bigint", nullable="false")
     */
    private $b_id;

    /**
     * @OneToOne(targetEntity="A", fetch="LAZY")
     * @JoinColumn(name="id", referencedColumnName="id")
     */
    private $a;

...

事实上,我所做的就是在我的实体中为相同的主键和外键写两个字段。

答案 3 :(得分:1)

这是插入的其他时间解决方案:

    /**
     * @Entity
     * @Table(name="types")
     */
    class Type {
    /**
     * @Id
     * @Column(type="integer")
     * @GeneratedValue
     */
    private $id;
    /**
     * @OneToMany(targetEntity="type\models\Language", mappedBy="type")
     */
    private $languages;

    /**
     * @Column(type="string", length = 45,nullable = true)
     */
    private $category;

    /**
     * @Column(type="string", length = 1)
     */
    private $status;

    /**
     * @Column(type="string", length = 45)
     */
    private $name;

    /**
     * @Column(type="datetime", nullable = true)
     */
    private $datedeleted;

    /**
     * @Column(type="datetime", nullable = true)
     */
    private $datemodificated;

    /**
     * @Column(type="datetime")
     */
    private $dateregistered;

    public function __construct() {
        $this->languages = new \Doctrine\Common\Collections\ArrayCollection;
        $this->status = 1;
        $this->dateregistered = new \DateTime("now");
    }

    public function id() {
            return $this->id;
    }

    public function category($value = NULL) {
        if (is_null($value))
            return $this->category;
        else
            $this->category = $value;
    }

    public function name($value = NULL) {
        if (is_null($value))
            return $this->name;
        else
            $this->name = $value;
    }

    public function status($value = NULL) {
        if (is_null($value))
            return $this->status;
        else
            $this->status = $value;
    }

    public function datedeleted($value = NULL) {
        if (is_null($value))
            return $this->datedeleted;
        else
            $this->datedeleted = $value;
    }

    public function datemodificated($value = NULL) {
        if (is_null($value))
            return $this->datemodificated;
        else
            $this->datemodificated = $value;
    }

    public function dateregistered($value = NULL) {
        if (is_null($value))
            return $this->dateregistered;
        else
            $this->dateregistered = $value;
        }
    }

    /**
     * @Entity
     * @Table(name="languages")
     */
    class Language {

    /**
     * @Id 
     * @Column(name="type_id", type="integer", nullable="false")
     */
    private $language_id;

    /**
     * @Id
     * @ManyToOne(targetEntity="type\models\Type",inversedBy="languages")
     * @JoinColumn(name="type_id", referencedColumnName="id")
     */
    private $type;

    /**
     * @Column(type="string", length = 100, nullable = true)
     */
    private $description;

    /**
     * @Id
     * @Column(type="string", length = 20)
     */
    private $language;

    public function language_id($value) {
        $this->language_id = $value;
    }

    public function description($value = NULL) {
        if (is_null($value))
            return $this->description;
        else
            $this->description = $value;
    }

    public function language($value = NULL) {
        if (is_null($value))
            return $this->language;
        else
            $this->language = $value;
    }

    public function type($value = NULL) {
        if (is_null($value))
            return $this->type;
        else
            $this->type = $value;


     }
    }

$language = new Language;
$xtype_id = $this->em->find("Type",1);
$language->language_id($xtype_id->id());
$language->type($xtype_id);
$language->description($xdescription);
$language->language($xlanguage);
$this->em->persist($this);
$this->em->flush();

此类插入使用语言中的外键和主键

答案 4 :(得分:1)

我有同样的任务,并且通过实验找到了这个解决方案:

class A {  
    /**  
    * @Id @Column(type="integer", nullable=false)  
    * @GeneratedValue  
    */  
    protected $id;  

    /**  
     * @OneToOne(targetEntity="B", inversedBy="a", orphanRemoval=true, cascade={"persist", "remove"})  
     * @JoinColumn(name="id", referencedColumnName="id")  
     */  
    protected $b;  

}  

class B {  
    /**  
     * @OneToOne(targetEntity="A", mappedBy="b" )  
     */  
    protected $user;  

    /**  
     * @Id  
     * @Column(type="integer", nullable=false)  
     * @GeneratedValue  
     */  
    protected $id;  

}