diff --git a/src/php/ContextFactory.php b/src/php/ContextFactory.php
index bbefa823f21280c1f934d1456f7ff76ee2a19a45..30ef01825c3f88bb1fda3c7575245435d6ea8107 100644
--- a/src/php/ContextFactory.php
+++ b/src/php/ContextFactory.php
@@ -49,7 +49,10 @@ final class ContextFactory implements ContextFactoryInterface
     private $reflectionTypeFactory;
 
     /** @var TypeFactoryInterface */
-    private $builtinTypeFactory;
+    private $builtinClassesTypeFactory;
+
+    /** @var TypeFactoryInterface */
+    private $builtinScalarsTypeFactory;
 
     /**
      * ContextFactory constructor.
@@ -60,7 +63,8 @@ final class ContextFactory implements ContextFactoryInterface
         $this->nullableTypeFactory = new NullableTypeFactory();
         $this->collectionTypeFactory = new CollectionTypeFactory();
         $this->reflectionTypeFactory = TypeCache::decorate(new ReflectionTypeFactory($propertyInfoExtractor));
-        $this->builtinTypeFactory = BuiltinTypeFactory::createDefault();
+        $this->builtinClassesTypeFactory = BuiltinTypeFactory::createWithClasses();
+        $this->builtinScalarsTypeFactory = BuiltinTypeFactory::createWithScalars();
     }
 
     /**
@@ -74,13 +78,14 @@ final class ContextFactory implements ContextFactoryInterface
             new CompositeTypeFactory([
                 $this->nullableTypeFactory,
                 $this->collectionTypeFactory,
+                $this->builtinClassesTypeFactory,
                 DeferrableTypeFactory::decorate(
                     new CompositeTypeFactory([
                         $serializationMapper,
                         $this->reflectionTypeFactory
                     ])
                 ),
-                $this->builtinTypeFactory
+                $this->builtinScalarsTypeFactory
             ])
         );
 
diff --git a/src/php/ModelGenerator.php b/src/php/ModelGenerator.php
index a4c4c05d0b334a74ea3994e89e588562214854c6..31af395056502df38a44a7319894565ba3bc1813 100644
--- a/src/php/ModelGenerator.php
+++ b/src/php/ModelGenerator.php
@@ -193,14 +193,6 @@ final class ModelGenerator
     {
         $repositories = [];
 
-//        // Premier passage pour prégénérer des références aux ressources
-//        foreach ($this->getResourceMetadata() as $class => $resourceMeta) {
-//            /* @var ClassName $class */
-//            /* @var ResourceMetadata $resourceMeta */
-//            $ref = $this->typeFactory->defer($class->getFullName());
-//            $this->typeFactory->add($resourceMeta->getBaseName(), $ref);
-//        }
-
         // Maintenant on génére les repositories
         foreach ($this->getResourceMetadata() as $class => $resourceMeta) {
             /* @var ClassName $class */
diff --git a/src/php/Models/Types/Factory/BuiltinTypeFactory.php b/src/php/Models/Types/Factory/BuiltinTypeFactory.php
index fa27f52fe20539c09ba3254c4f235de18d998391..20025a2cb97e8ea3f692ee876307a1a968e1ae5f 100644
--- a/src/php/Models/Types/Factory/BuiltinTypeFactory.php
+++ b/src/php/Models/Types/Factory/BuiltinTypeFactory.php
@@ -65,7 +65,7 @@ class BuiltinTypeFactory implements TypeFactoryInterface
      */
     public function createType(PropertyType $type, ContextInterface $context): Type
     {
-        Assertion::true($this->supportsType($type, $context));
+        Assertion::true($this->supportsType($type, $context), '%s is not supported by '. static::class);
 
         return $this->types[TypeHelper::getTypeKey($type)];
     }
@@ -73,7 +73,7 @@ class BuiltinTypeFactory implements TypeFactoryInterface
     /**
      * @return BuiltinTypeFactory
      */
-    public static function createDefault(): BuiltinTypeFactory
+    public static function createWithScalars(): BuiltinTypeFactory
     {
         $types = [
             PropertyType::BUILTIN_TYPE_ARRAY  => BuiltinType::get('Array'),
@@ -82,13 +82,26 @@ class BuiltinTypeFactory implements TypeFactoryInterface
             PropertyType::BUILTIN_TYPE_INT    => BuiltinType::get('number'),
             PropertyType::BUILTIN_TYPE_NULL   => BuiltinType::get('null'),
             PropertyType::BUILTIN_TYPE_STRING => BuiltinType::get('string'),
-            'Ramsey\Uuid\UuidInterface'       => UUID::get(),
-            'DateTime'                        => BuiltinType::get('string'),
-            'DateTimeInterface'               => BuiltinType::get('string'),
-            'DateTimeImmutable'               => BuiltinType::get('string'),
-            'Ordering'                        => new Alias('Ordering', Union::create([StringConst::get('asc'), StringConst::get('desc')]), 'Allowed values for ordering parameters'),
         ];
 
         return new BuiltinTypeFactory($types);
     }
+
+    /**
+     * @return BuiltinTypeFactory
+     */
+    public static function createWithClasses(): BuiltinTypeFactory
+    {
+        $types = [
+            'Ramsey\Uuid\Uuid' => UUID::get(),
+            'Ramsey\Uuid\UuidInterface' => UUID::get(),
+            'DateTime' => BuiltinType::get('string'),
+            'DateTimeInterface' => BuiltinType::get('string'),
+            'DateTimeImmutable' => BuiltinType::get('string'),
+            'Ordering' => new Alias('Ordering', Union::create([StringConst::get('asc'), StringConst::get('desc')]), 'Allowed values for ordering parameters'),
+        ];
+
+        return new BuiltinTypeFactory($types);
+    }
+
 }
diff --git a/src/php/Models/Types/Factory/CollectionTypeFactory.php b/src/php/Models/Types/Factory/CollectionTypeFactory.php
index efac62781466b8a22bff16f5c8b031ba58ffe439..84bfc3208ad99a418287b7b782d4a6b16c60ba7c 100644
--- a/src/php/Models/Types/Factory/CollectionTypeFactory.php
+++ b/src/php/Models/Types/Factory/CollectionTypeFactory.php
@@ -46,7 +46,7 @@ final class CollectionTypeFactory implements TypeFactoryInterface
      */
     public function createType(PropertyType $type, ContextInterface $context): Type
     {
-        Assertion::true($this->supportsType($type, $context));
+        Assertion::true($this->supportsType($type, $context), '%s is not supported by ' . static::class);
 
         $valueType = $type->getCollectionValueType();
         if (!$valueType) {
diff --git a/src/php/Models/Types/Factory/NullableTypeFactory.php b/src/php/Models/Types/Factory/NullableTypeFactory.php
index 7b986abba973b92c05789c764ea14bd4f3f576dc..11e71ff818a1aef9103f387e9ba2ee41c44efe17 100644
--- a/src/php/Models/Types/Factory/NullableTypeFactory.php
+++ b/src/php/Models/Types/Factory/NullableTypeFactory.php
@@ -45,7 +45,7 @@ final class NullableTypeFactory implements TypeFactoryInterface
      */
     public function createType(PropertyType $type, ContextInterface $context): Type
     {
-        Assertion::true($this->supportsType($type, $context));
+        Assertion::true($this->supportsType($type, $context), '%s is not supported by ' . static::class);
 
         return Union::create([BuiltinType::get('null'), $context->createType(TypeHelper::notNullable($type))]);
     }
diff --git a/src/php/Models/Types/Factory/ReflectionTypeFactory.php b/src/php/Models/Types/Factory/ReflectionTypeFactory.php
index 76d75e0aed5f2082b7f13e9adf274a5d61898231..00788752b1bebf79cf241a5c010685640c9a7de7 100644
--- a/src/php/Models/Types/Factory/ReflectionTypeFactory.php
+++ b/src/php/Models/Types/Factory/ReflectionTypeFactory.php
@@ -62,7 +62,7 @@ final class ReflectionTypeFactory implements TypeFactoryInterface
      */
     public function createType(PropertyType $type, ContextInterface $context): Type
     {
-        Assertion::true($this->supportsType($type, $context));
+        Assertion::true($this->supportsType($type, $context), '%s is not supported by ' . static::class);
 
         $fqcn = $type->getClassName();
         $propertyNames = $this->propertyInfoExtractor->getProperties($fqcn);
diff --git a/src/php/Models/Types/Factory/TypeCache.php b/src/php/Models/Types/Factory/TypeCache.php
index e6db8591b377fe30a5ddb393db909cf7dd35f679..1f0a53db94b6e530ef2edc443776d30ba249210d 100644
--- a/src/php/Models/Types/Factory/TypeCache.php
+++ b/src/php/Models/Types/Factory/TypeCache.php
@@ -59,7 +59,7 @@ final class TypeCache extends AbstractTypeFactoryDecorator
      */
     public function createType(PropertyType $type, ContextInterface $context): Type
     {
-        Assertion::true($this->supportsType($type, $context));
+        Assertion::true($this->supportsType($type, $context), $type->getClassName() . ' is not supported by ' . static::class);
 
         $key = TypeHelper::getTypeKey($type);
 
diff --git a/src/php/SerializationMapper.php b/src/php/SerializationMapper.php
index 75989664e278088ba7873c4d5ac99a7b6412845c..2bfa3f149ec4f5572263678233cb436921f421a0 100644
--- a/src/php/SerializationMapper.php
+++ b/src/php/SerializationMapper.php
@@ -180,28 +180,14 @@ final class SerializationMapper implements TypeFactoryInterface
     private function mapProperties(ClassInfo $classInfo, ContextInterface $context): array
     {
         $properties = [];
-        $identifierCount = 0;
 
         foreach ($classInfo->getConcreteProperties() as $propertyMeta) {
             /** @var PropertyMetadata $propertyMeta */
-            if ($propertyMeta->isIdentifier()) {
-                ++$identifierCount;
-            }
 
             $property = $this->mapProperty($propertyMeta, $context);
             $properties[$property->getName()] = $property;
         }
 
-        if ($identifierCount > 1) {
-            throw new DomainException(
-                sprintf(
-                    'Resource %s must have at most one identifier, found %d',
-                    $classInfo->getBaseName(),
-                    $identifierCount
-                )
-            );
-        }
-
         if ($this->withAtFields && $classInfo->isResource()) {
             $properties['@id'] = new Property(
                 '@id',
diff --git a/tests/Fixtures/Entity/EntityTrait.php b/tests/Fixtures/Entity/EntityTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..c017e0adec3b10a3854ed293ca527a72135fdc89
--- /dev/null
+++ b/tests/Fixtures/Entity/EntityTrait.php
@@ -0,0 +1,49 @@
+<?php declare(strict_types=1);
+/**
+ * Copyright (C) 2019 IRSTEA
+ * All rights reserved.
+ *
+ * @copyright 2019 IRSTEA
+ * @author guillaume.perreal
+ */
+
+
+namespace Irstea\NgModelGeneratorBundle\Tests\Fixtures\Entity;
+
+
+use Doctrine\ORM\Mapping as ORM;
+use Ramsey\Uuid\Uuid;
+
+/**
+ * Class EntityTrait
+ */
+trait EntityTrait
+{
+    /**
+     * N.B. : il est nécessaire d'utiliser le FQCN ici sinon le lecteur d'annotation bug
+     * et ne retrouve pas le bon namespace.
+     *
+     * @var \Ramsey\Uuid\UuidInterface
+     * @ORM\Id()
+     * @ORM\Column(type="uuid", unique=true)
+     */
+    private $id;
+
+    /**
+     * @throws \Exception
+     */
+    private function createId()
+    {
+        $this->id = Uuid::uuid4();
+    }
+
+    /**
+     * Get id.
+     *
+     * @return \Ramsey\Uuid\UuidInterface
+     */
+    public function getId(): \Ramsey\Uuid\UuidInterface
+    {
+        return $this->id;
+    }
+}
diff --git a/tests/Fixtures/Entity/Person.php b/tests/Fixtures/Entity/Person.php
index 3bc68a7e77df4c6d372d0a46e223079476fd0417..55b876e7899806e0c9e12ba59c3712fd4c675ba6 100644
--- a/tests/Fixtures/Entity/Person.php
+++ b/tests/Fixtures/Entity/Person.php
@@ -15,8 +15,6 @@ use ApiPlatform\Core\Annotation as API;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
-use Ramsey\Uuid\Uuid;
-use Ramsey\Uuid\UuidInterface;
 use Symfony\Component\Validator\Constraints as Assert;
 
 /**
@@ -27,25 +25,8 @@ use Symfony\Component\Validator\Constraints as Assert;
  */
 final class Person
 {
-    /**
-     * @var UuidInterface
-     * @ORM\Id()
-     * @ORM\Column(type="uuid")
-     */
-    private $id;
-
-    /**
-     * @var \DateTimeInterface
-     * @ORM\Column(type="datetimetz_immutable")
-     * @Assert\NotNull()
-     */
-    private $createdAt;
-
-    /**
-     * @var \DateTimeInterface|null
-     * @ORM\Column(type="datetimetz_immutable", nullable=true)
-     */
-    private $updatedAt;
+    use EntityTrait;
+    use TimestampedTrait;
 
     /**
      * @var string
@@ -85,17 +66,26 @@ final class Person
      */
     private $participeTo;
 
+    /**
+     * @var Structure|null
+     * @ORM\ManyToOne(targetEntity=Structure::class)
+     */
+    private $affectation;
+
     /**
      * Person constructor.
      * @param string $firstName
      * @param string $lastName
      * @param string|null $email
      * @param string|null $phoneNumber
+     * @param Structure|null $affectation
+     * @throws \Exception
      */
-    public function __construct(string $firstName, string $lastName, string $email = null, string $phoneNumber = null)
+    public function __construct(string $firstName, string $lastName, string $email = null, string $phoneNumber = null, Structure $affectation = null)
     {
-        $this->id = Uuid::uuid4();
-        $this->createdAt = new \DateTimeImmutable();
+        $this->createId();
+        $this->created();
+
         $this->firstName = $firstName;
         $this->lastName = $lastName;
         $this->email = $email;
@@ -103,36 +93,7 @@ final class Person
 
         $this->managedProjects = new ArrayCollection();
         $this->participeTo = new ArrayCollection();
-    }
-
-    /**
-     * Get id.
-     *
-     * @return UuidInterface
-     */
-    public function getId(): UuidInterface
-    {
-        return $this->id;
-    }
-
-    /**
-     * Get createdAt.
-     *
-     * @return \DateTimeInterface
-     */
-    public function getCreatedAt(): \DateTimeInterface
-    {
-        return $this->createdAt;
-    }
-
-    /**
-     * Get updatedAt.
-     *
-     * @return \DateTimeInterface|null
-     */
-    public function getUpdatedAt(): ?\DateTimeInterface
-    {
-        return $this->updatedAt;
+        $this->affectation = $affectation;
     }
 
     /**
@@ -175,6 +136,16 @@ final class Person
         return $this->phoneNumber;
     }
 
+    /**
+     * Get affectation.
+     *
+     * @return Structure|null
+     */
+    public function getAffectation(): ?Structure
+    {
+        return $this->affectation;
+    }
+
     /**
      * Set firstName.
      *
@@ -183,7 +154,7 @@ final class Person
     public function setFirstName(string $firstName): void
     {
         $this->firstName = $firstName;
-        $this->updatedAt = new \DateTimeImmutable();
+        $this->updated();
     }
 
     /**
@@ -194,7 +165,7 @@ final class Person
     public function setLastName(string $lastName): void
     {
         $this->lastName = $lastName;
-        $this->updatedAt = new \DateTimeImmutable();
+        $this->updated();
     }
 
     /**
@@ -205,7 +176,7 @@ final class Person
     public function setEmail(?string $email): void
     {
         $this->email = $email;
-        $this->updatedAt = new \DateTimeImmutable();
+        $this->updated();
     }
 
     /**
@@ -216,7 +187,18 @@ final class Person
     public function setPhoneNumber(?string $phoneNumber): void
     {
         $this->phoneNumber = $phoneNumber;
-        $this->updatedAt = new \DateTimeImmutable();
+        $this->updated();
+    }
+
+    /**
+     * Set affectation.
+     *
+     * @param Structure|null $affectation
+     */
+    public function setAffectation(?Structure $affectation): void
+    {
+        $this->affectation = $affectation;
+        $this->updated();
     }
 
     /**
diff --git a/tests/Fixtures/Entity/Project.php b/tests/Fixtures/Entity/Project.php
index bf3da48645b5c737714e0609b1937891ed5eb491..e56993fa97b171e789af2dfc5e184e5159a39b0e 100644
--- a/tests/Fixtures/Entity/Project.php
+++ b/tests/Fixtures/Entity/Project.php
@@ -16,7 +16,6 @@ use Assert\Assertion;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
-use Ramsey\Uuid\Uuid;
 use Ramsey\Uuid\UuidInterface;
 use Symfony\Component\Validator\Constraints as Assert;
 
@@ -28,12 +27,8 @@ use Symfony\Component\Validator\Constraints as Assert;
  */
 final class Project
 {
-    /**
-     * @var UuidInterface
-     * @ORM\Id()
-     * @ORM\Column(type="uuid")
-     */
-    private $id;
+    use EntityTrait;
+    use TimestampedTrait;
 
     /**
      * @ORM\Column()
@@ -78,7 +73,9 @@ final class Project
      */
     public function __construct(string $name, ?string $acronym, \DateTimeImmutable $startDate, Person $manager, array $participants)
     {
-        $this->id = Uuid::uuid4();
+        $this->createId();
+        $this->created();
+
         $this->name = $name;
         $this->acronym = $acronym;
         $this->startDate = $startDate;
@@ -116,6 +113,7 @@ final class Project
     public function setName(string $name): void
     {
         $this->name = $name;
+        $this->updated();
     }
 
     /**
@@ -136,6 +134,7 @@ final class Project
     public function setAcronym(?string $acronym): void
     {
         $this->acronym = $acronym;
+        $this->updated();
     }
 
     /**
@@ -156,6 +155,7 @@ final class Project
     public function setStartDate(\DateTimeImmutable $startDate): void
     {
         $this->startDate = $startDate;
+        $this->updated();
     }
 
     /**
@@ -176,6 +176,7 @@ final class Project
     public function setManager(Person $manager): void
     {
         $this->manager = $manager;
+        $this->updated();
     }
 
     /**
@@ -197,6 +198,7 @@ final class Project
     {
         if (!$this->participants->contains($person)) {
             $this->participants->add($person);
+            $this->updated();
         }
     }
 
@@ -207,7 +209,9 @@ final class Project
      */
     public function removeParticipant(Person $person): void
     {
-        $this->participants->removeElement($person);
+        if ($this->participants->contains($person)) {
+            $this->participants->removeElement($person);
+            $this->updated();
+        }
     }
-
 }
diff --git a/tests/Fixtures/Entity/Structure.php b/tests/Fixtures/Entity/Structure.php
new file mode 100644
index 0000000000000000000000000000000000000000..c3653511d22359820073035a7e749b9166b691de
--- /dev/null
+++ b/tests/Fixtures/Entity/Structure.php
@@ -0,0 +1,114 @@
+<?php declare(strict_types=1);
+/**
+ * Copyright (C) 2019 IRSTEA
+ * All rights reserved.
+ *
+ * @copyright 2019 IRSTEA
+ * @author guillaume.perreal
+ */
+
+
+namespace Irstea\NgModelGeneratorBundle\Tests\Fixtures\Entity;
+
+
+use ApiPlatform\Core\Annotation as API;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * Class Structure
+ *
+ * @ORM\Entity()
+ * @API\ApiResource()
+ */
+class Structure
+{
+    use EntityTrait;
+    use TimestampedTrait;
+
+    /**
+     * @ORM\Column()
+     * @var string
+     */
+    private $name;
+
+    /**
+     * @var Structure|null
+     * @ORM\ManyToOne(targetEntity=Structure::class, inversedBy="children")
+     */
+    private $parent;
+
+    /**
+     * @var Structure[]|Collection
+     * @ORM\OneToMany(targetEntity=Structure::class, mappedBy="parent")
+     */
+    private $children;
+
+    /**
+     * Structure constructor.
+     * @param string $name
+     * @param Structure|null $parent
+     */
+    public function __construct(string $name, self $parent = null)
+    {
+        $this->createId();
+        $this->created();
+
+        $this->name = $name;
+        $this->parent = $parent;
+        $this->children = New ArrayCollection();
+    }
+
+    /**
+     * Get name.
+     *
+     * @return string
+     */
+    public function getName(): string
+    {
+        return $this->name;
+    }
+
+    /**
+     * Get parent.
+     *
+     * @return Structure|null
+     */
+    public function getParent(): ?Structure
+    {
+        return $this->parent;
+    }
+
+    /**
+     * Set name.
+     *
+     * @param string $name
+     */
+    public function setName(string $name): void
+    {
+        $this->name = $name;
+        $this->updated();
+    }
+
+    /**
+     * Set parent.
+     *
+     * @param Structure|null $parent
+     */
+    public function setParent(?Structure $parent): void
+    {
+        $this->parent = $parent;
+        $this->updated();
+    }
+
+    /**
+     * Get children.
+     *
+     * @return Structure[]
+     */
+    public function getChildren(): array
+    {
+        return $this->children->toArray();
+    }
+}
diff --git a/tests/Fixtures/Entity/TimestampedTrait.php b/tests/Fixtures/Entity/TimestampedTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..1ab137167297df26b94cff002bbfbc441fd61c76
--- /dev/null
+++ b/tests/Fixtures/Entity/TimestampedTrait.php
@@ -0,0 +1,61 @@
+<?php declare(strict_types=1);
+/**
+ * Copyright (C) 2019 IRSTEA
+ * All rights reserved.
+ *
+ * @copyright 2019 IRSTEA
+ * @author guillaume.perreal
+ */
+
+
+namespace Irstea\NgModelGeneratorBundle\Tests\Fixtures\Entity;
+
+
+/**
+ * Trait TimestampedTrait
+ */
+trait TimestampedTrait
+{
+    /**
+     * @var \DateTimeInterface
+     * @ORM\Column(type="datetimetz_immutable")
+     */
+    private $createdAt;
+
+    /**
+     * @var \DateTimeInterface|null
+     * @ORM\Column(type="datetimetz_immutable", nullable=true)
+     */
+    private $updatedAt;
+
+    protected function created(): void
+    {
+        $this->createdAt = new \DateTimeImmutable();
+    }
+
+    protected function updated(): void
+    {
+        $this->updatedAt = new \DateTimeImmutable();
+    }
+
+    /**
+     * Get createdAt.
+     *
+     * @return \DateTimeInterface
+     */
+    public function getCreatedAt(): \DateTimeInterface
+    {
+        return $this->createdAt;
+    }
+
+    /**
+     * Get updatedAt.
+     *
+     * @return \DateTimeInterface|null
+     */
+    public function getUpdatedAt(): ?\DateTimeInterface
+    {
+        return $this->updatedAt;
+    }
+
+}