diff --git a/lib/Doctrine/ORM/Id/AssignedGenerator.php b/lib/Doctrine/ORM/Id/AssignedGenerator.php
index f4bd3d6..e1981fe 100644
--- a/lib/Doctrine/ORM/Id/AssignedGenerator.php
+++ b/lib/Doctrine/ORM/Id/AssignedGenerator.php
@@ -49,7 +49,12 @@ class AssignedGenerator extends AbstractIdGenerator
             foreach ($idFields as $idField) {
                 $value = $class->getReflectionProperty($idField)->getValue($entity);
                 if (isset($value)) {
-                    $identifier[$idField] = $value;
+                    if (is_object($value)) {
+                        // TODO: Single Id only, i enforce that. Compoite Key as Foreign Keys Primary Key part sounds ugly
+                        $identifier[$idField] = current($em->getUnitOfWork()->getEntityIdentifier($value));
+                    } else {
+                        $identifier[$idField] = $value;
+                    }
                 } else {
                     throw ORMException::entityMissingAssignedId($entity);
                 }
@@ -58,7 +63,12 @@ class AssignedGenerator extends AbstractIdGenerator
             $idField = $class->identifier[0];
             $value = $class->reflFields[$idField]->getValue($entity);
             if (isset($value)) {
-                $identifier[$idField] = $value;
+                if (is_object($value)) {
+                    // TODO: Single Id only, i enforce that. Compoite Key as Foreign Keys Primary Key part sounds ugly
+                    $identifier[$idField] = current($em->getUnitOfWork()->getEntityIdentifier($value));
+                } else {
+                    $identifier[$idField] = $value;
+                }
             } else {
                 throw ORMException::entityMissingAssignedId($entity);
             }
diff --git a/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
index 5ce4621..ad8c084 100644
--- a/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
+++ b/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
@@ -190,9 +190,11 @@ abstract class AbstractHydrator
                     continue;
                 } else {
                     // Meta column (has meaning in relational schema only, i.e. foreign keys or discriminator columns).
+                    $fieldName = $this->_rsm->metaMappings[$key];
                     $cache[$key]['isMetaColumn'] = true;
-                    $cache[$key]['fieldName'] = $this->_rsm->metaMappings[$key];
+                    $cache[$key]['fieldName'] = $fieldName;
                     $cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
+                    $cache[$key]['isIdentifier'] = $classMetadata->isIdentifier($fieldName);
                 }
             }
             
@@ -203,15 +205,15 @@ abstract class AbstractHydrator
 
             $dqlAlias = $cache[$key]['dqlAlias'];
 
+            if ($cache[$key]['isIdentifier']) {
+                $id[$dqlAlias] .= '|' . $value;
+            }
+
             if (isset($cache[$key]['isMetaColumn'])) {
                 $rowData[$dqlAlias][$cache[$key]['fieldName']] = $value;
                 continue;
             }
 
-            if ($cache[$key]['isIdentifier']) {
-                $id[$dqlAlias] .= '|' . $value;
-            }
-
             $rowData[$dqlAlias][$cache[$key]['fieldName']] = $cache[$key]['type']->convertToPHPValue($value, $this->_platform);
 
             if ( ! isset($nonemptyComponents[$dqlAlias]) && $value !== null) {
diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
index 2d6ec7c..53042d0 100644
--- a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
+++ b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
@@ -710,6 +710,18 @@ class ClassMetadataInfo
             $mapping['targetEntity'] = $this->namespace . '\\' . $mapping['targetEntity'];
         }
 
+        // Complete id mapping
+        if (isset($mapping['id']) && $mapping['id'] === true) {
+            if ( ! in_array($mapping['fieldName'], $this->identifier)) {
+                $this->identifier[] = $mapping['fieldName'];
+            }
+            // Check for composite key
+            if ( ! $this->isIdentifierComposite && count($this->identifier) > 1) {
+                $this->isIdentifierComposite = true;
+            }
+        }
+
+        // Mandatory attributes for both sides
         // Mandatory: fieldName, targetEntity
         if ( ! isset($mapping['fieldName'])) {
             throw MappingException::missingFieldName();
@@ -981,7 +993,11 @@ class ClassMetadataInfo
         if ($this->isIdentifierComposite) {
             $columnNames = array();
             foreach ($this->identifier as $idField) {
-                $columnNames[] = $this->fieldMappings[$idField]['columnName'];
+                if (isset($this->associationMappings[$idField])) {
+                    $columnNames[] = $this->associationMappings[$idField]['joinColumns'][0]['name'];
+                } else {
+                    $columnNames[] = $this->fieldMappings[$idField]['columnName'];
+                }
             }
             return $columnNames;
         } else {
@@ -1250,6 +1266,34 @@ class ClassMetadataInfo
     }
 
     /**
+     * Makes some automatic additions to the association mapping to make the life
+     * easier for the user, and store join columns in the metadata.
+     *
+     * @param array $mapping
+     * @todo Pass param by ref?
+     */
+    private function _completeAssociationMapping(array $mapping)
+    {
+        $mapping['sourceEntity'] = $this->name;
+        if (isset($mapping['targetEntity']) && strpos($mapping['targetEntity'], '\\') === false && strlen($this->namespace) > 0) {
+            $mapping['targetEntity'] = $this->namespace . '\\' . $mapping['targetEntity'];
+        }
+
+        // Complete id mapping
+        if (isset($mapping['id']) && $mapping['id'] === true) {
+            if ( ! in_array($mapping['fieldName'], $this->identifier)) {
+                $this->identifier[] = $mapping['fieldName'];
+            }
+            // Check for composite key
+            if ( ! $this->isIdentifierComposite && count($this->identifier) > 1) {
+                $this->isIdentifierComposite = true;
+            }
+        }
+        
+        return $mapping;
+    }
+
+    /**
      * Adds a mapped field to the class.
      *
      * @param array $mapping The field mapping.
@@ -1592,4 +1636,4 @@ class ClassMetadataInfo
     {
         $this->versionField = $versionField;
     }
-}
\ No newline at end of file
+}
diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
index 115d6db..81dcc90 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
@@ -288,6 +288,10 @@ class AnnotationDriver implements Driver
                     throw MappingException::tableIdGeneratorNotImplemented($className);
                 }
             } else if ($oneToOneAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OneToOne')) {
+                if ($idAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Id')) {
+                    $mapping['id'] = true;
+                }
+
                 $mapping['targetEntity'] = $oneToOneAnnot->targetEntity;
                 $mapping['joinColumns'] = $joinColumns;
                 $mapping['mappedBy'] = $oneToOneAnnot->mappedBy;
@@ -309,6 +313,10 @@ class AnnotationDriver implements Driver
 
                 $metadata->mapOneToMany($mapping);
             } else if ($manyToOneAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\ManyToOne')) {
+                if ($idAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Id')) {
+                    $mapping['id'] = true;
+                }
+
                 $mapping['joinColumns'] = $joinColumns;
                 $mapping['cascade'] = $manyToOneAnnot->cascade;
                 $mapping['inversedBy'] = $manyToOneAnnot->inversedBy;
diff --git a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php
index 2903ac9..8e98191 100644
--- a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php
+++ b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php
@@ -313,9 +313,16 @@ class BasicEntityPersister
         $where = array();
         $id = $this->_em->getUnitOfWork()->getEntityIdentifier($entity);
         foreach ($this->_class->identifier as $idField) {
-            $where[] = $this->_class->getQuotedColumnName($idField, $this->_platform);
-            $params[] = $id[$idField];
-            $types[] = $this->_class->fieldMappings[$idField]['type'];
+            if (isset($this->_class->associationMappings[$idField])) {
+                $targetMapping = $this->_em->getClassMetadata($this->_class->associationMappings[$idField]['targetEntity']);
+                $where[] = $this->_class->associationMappings[$idField]['joinColumns'][0]['name'];
+                $params[] = $id[$idField];
+                $types[] = $targetMapping->fieldMappings[$targetMapping->identifier[0]]['type'];
+            } else {
+                $where[] = $this->_class->getQuotedColumnName($idField, $this->_platform);
+                $params[] = $id[$idField];
+                $types[] = $this->_class->fieldMappings[$idField]['type'];
+            }
         }
 
         if ($versioned) {
@@ -1124,6 +1131,7 @@ class BasicEntityPersister
                 }
                 $conditionSql .= $this->_class->getQuotedColumnName($field, $this->_platform);
             } else if (isset($this->_class->associationMappings[$field])) {
+                // TODO: Composite Keys as Foreign Key PK? That would be super ugly! And should probably be disallowed ;)
                 if (!$this->_class->associationMappings[$field]['isOwningSide']) {
                     throw ORMException::invalidFindByInverseAssociation($this->_class->name, $field);
                 }
@@ -1133,7 +1141,6 @@ class BasicEntityPersister
                 } else {
                     $conditionSql .= $this->_getSQLTableAlias($this->_class->name) . '.';
                 }
-                
 
                 $conditionSql .= $this->_class->associationMappings[$field]['joinColumns'][0]['name'];
             } else if ($assoc !== null) {
diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php
index 31f75f0..1512da2 100644
--- a/lib/Doctrine/ORM/Query/SqlWalker.php
+++ b/lib/Doctrine/ORM/Query/SqlWalker.php
@@ -970,6 +970,27 @@ class SqlWalker implements TreeWalker
                 $this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $class->name);
             }
 
+            // Add double entry for association identifier columns to simplify hydrator code
+            foreach ($class->identifier AS $idField) {
+                if (isset($class->associationMappings[$idField])) {
+                    if (isset($mapping['inherited'])) {
+                        $tableName = $this->_em->getClassMetadata($mapping['inherited'])->table['name'];
+                    } else {
+                        $tableName = $class->table['name'];
+                    }
+
+                    if ($beginning) $beginning = false; else $sql .= ', ';
+
+                    $joinColumnName = $class->associationMappings[$idField]['joinColumns'][0]['name'];
+                    $sqlTableAlias = $this->getSqlTableAlias($tableName, $dqlAlias);
+                    $columnAlias = $this->getSqlColumnAlias($joinColumnName);
+                    $sql .= $sqlTableAlias . '.' . $joinColumnName . ' AS ' . $columnAlias;
+
+                    $columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
+                    $this->_rsm->addMetaResult($dqlAlias, $columnAlias, $idField);
+                }
+            }
+
             // Add any additional fields of subclasses (excluding inherited fields)
             // 1) on Single Table Inheritance: always, since its marginal overhead
             // 2) on Class Table Inheritance only if partial objects are disallowed,
diff --git a/lib/Doctrine/ORM/Tools/SchemaTool.php b/lib/Doctrine/ORM/Tools/SchemaTool.php
index e87a99a..30d6db2 100644
--- a/lib/Doctrine/ORM/Tools/SchemaTool.php
+++ b/lib/Doctrine/ORM/Tools/SchemaTool.php
@@ -199,6 +199,22 @@ class SchemaTool
                 $this->_gatherRelationsSql($class, $table, $schema);
             }
 
+            $pkColumns = array();
+            foreach ($class->identifier AS $identifierField) {
+                if (isset($class->fieldMappings[$identifierField])) {
+                    $pkColumns[] = $class->getQuotedColumnName($identifierField, $this->_platform);
+                } else if (isset($class->associationMappings[$identifierField])) {
+                    /* @var $assoc \Doctrine\ORM\Mapping\OneToOne */
+                    $assoc = $class->associationMappings[$identifierField];
+                    foreach ($assoc['joinColumns'] AS $joinColumn) {
+                        $pkColumns[] = $joinColumn['name'];
+                    }
+                }
+            }
+            if (!$table->hasIndex('primary')) {
+                $table->setPrimaryKey($pkColumns);
+            }
+
             if (isset($class->table['indexes'])) {
                 foreach ($class->table['indexes'] AS $indexName => $indexData) {
                     $table->addIndex($indexData['columns'], $indexName);
@@ -281,10 +297,11 @@ class SchemaTool
                 $pkColumns[] = $class->getQuotedColumnName($mapping['fieldName'], $this->_platform);
             }
         }
+
         // For now, this is a hack required for single table inheritence, since this method is called
         // twice by single table inheritence relations
         if(!$table->hasIndex('primary')) {
-            $table->setPrimaryKey($pkColumns);
+            //$table->setPrimaryKey($pkColumns);
         }
 
         return $columns;
diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php
index 76ce521..1f05ced 100644
--- a/lib/Doctrine/ORM/UnitOfWork.php
+++ b/lib/Doctrine/ORM/UnitOfWork.php
@@ -1837,11 +1837,19 @@ class UnitOfWork implements PropertyChangedListener
         if ($class->isIdentifierComposite) {
             $id = array();
             foreach ($class->identifier as $fieldName) {
-                $id[$fieldName] = $data[$fieldName];
+                if (isset($class->associationMappings[$fieldName])) {
+                    $id[$fieldName] = $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']];
+                } else {
+                    $id[$fieldName] = $data[$fieldName];
+                }
             }
             $idHash = implode(' ', $id);
         } else {
-            $idHash = $data[$class->identifier[0]];
+            if (isset($class->associationMappings[$class->identifier[0]])) {
+                $idHash = $data[$class->associationMappings[$class->identifier[0]]['joinColumns'][0]['name']];
+            } else {
+                $idHash = $data[$class->identifier[0]];
+            }
             $id = array($class->identifier[0] => $idHash);
         }
 
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC117Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC117Test.php
new file mode 100644
index 0000000..e7e9947
--- /dev/null
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC117Test.php
@@ -0,0 +1,427 @@
+<?php
+
+namespace Doctrine\Tests\ORM\Functional\Ticket;
+
+require_once __DIR__ . '/../../../TestInit.php';
+
+class DDC117Test extends \Doctrine\Tests\OrmFunctionalTestCase
+{
+    private $article1;
+    private $article2;
+    private $reference;
+    private $translation;
+    private $articleDetails;
+
+    protected function setUp() {
+        parent::setUp();
+
+        try {
+            $this->_schemaTool->createSchema(array(
+                $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC117Article'),
+                $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC117Reference'),
+                $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC117Translation'),
+                $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC117ArticleDetails'),
+            ));
+        } catch(\Exception $e) {
+
+        }
+
+        $this->article1 = new DDC117Article("Foo");
+        $this->article2 = new DDC117Article("Bar");
+
+        $this->_em->persist($this->article1);
+        $this->_em->persist($this->article2);
+        $this->_em->flush();
+
+        $this->reference = new DDC117Reference($this->article1, $this->article2, "Test-Description");
+        $this->_em->persist($this->reference);
+
+        $this->translation = new DDC117Translation($this->article1, "en", "Bar");
+        $this->_em->persist($this->translation);
+
+        $this->articleDetails = new DDC117ArticleDetails($this->article1, "Very long text");
+        $this->_em->persist($this->articleDetails);
+        $this->_em->flush();
+
+        $this->_em->clear();
+    }
+
+    /**
+     * @group DDC-117
+     */
+    public function testAssociationOnlyCompositeKey()
+    {
+        $idCriteria = array('source' => $this->article1->id(), 'target' => $this->article2->id());
+
+        $mapRef = $this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria);
+        $this->assertType(__NAMESPACE__."\DDC117Reference", $mapRef);
+        $this->assertType(__NAMESPACE__."\DDC117Article", $mapRef->target());
+        $this->assertType(__NAMESPACE__."\DDC117Article", $mapRef->source());
+        $this->assertSame($mapRef, $this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria));
+
+        $this->_em->clear();
+
+        $dql = "SELECT r, s FROM ".__NAMESPACE__."\DDC117Reference r JOIN r.source s WHERE r.source = ?1";
+        $dqlRef = $this->_em->createQuery($dql)->setParameter(1, 1)->getSingleResult();
+
+        $this->assertType(__NAMESPACE__."\DDC117Reference", $mapRef);
+        $this->assertType(__NAMESPACE__."\DDC117Article", $mapRef->target());
+        $this->assertType(__NAMESPACE__."\DDC117Article", $mapRef->source());
+        $this->assertSame($dqlRef, $this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria));
+
+        $this->_em->clear();
+
+        $dql = "SELECT r, s FROM ".__NAMESPACE__."\DDC117Reference r JOIN r.source s WHERE s.title = ?1";
+        $dqlRef = $this->_em->createQuery($dql)->setParameter(1, 'Foo')->getSingleResult();
+
+        $this->assertType(__NAMESPACE__."\DDC117Reference", $dqlRef);
+        $this->assertType(__NAMESPACE__."\DDC117Article", $dqlRef->target());
+        $this->assertType(__NAMESPACE__."\DDC117Article", $dqlRef->source());
+        $this->assertSame($dqlRef, $this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria));
+
+        $dql = "SELECT r, s FROM ".__NAMESPACE__."\DDC117Reference r JOIN r.source s WHERE s.title = ?1";
+        $dqlRef = $this->_em->createQuery($dql)->setParameter(1, 'Foo')->getSingleResult();
+
+        $this->_em->contains($dqlRef);
+    }
+
+    /**
+     * @group DDC-117
+     */
+    public function testUpdateAssocationEntity()
+    {
+        $idCriteria = array('source' => $this->article1->id(), 'target' => $this->article2->id());
+
+        $mapRef = $this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria);
+        $this->assertNotNull($mapRef);
+        $mapRef->setDescription("New Description!!");
+        $this->_em->flush();
+        $this->_em->clear();
+
+        $mapRef = $this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria);
+
+        $this->assertEquals('New Description!!', $mapRef->getDescription());
+    }
+
+    /**
+     * @group DDC-117
+     */
+    public function testFetchDql()
+    {
+        $dql = "SELECT r, s FROM ".__NAMESPACE__."\DDC117Reference r JOIN r.source s WHERE s.title = ?1";
+        $refs = $this->_em->createQuery($dql)->setParameter(1, 'Foo')->getResult();
+
+        $this->assertTrue(count($refs) > 0, "Has to contain at least one Reference.");
+        foreach ($refs AS $ref) {
+            $this->assertType(__NAMESPACE__."\DDC117Reference", $ref, "Contains only Reference instances.");
+            $this->assertTrue($this->_em->contains($ref), "Contains Reference in the IdentityMap.");
+        }
+    }
+
+    /**
+     * @group DDC-117
+     */
+    public function testRemoveCompositeElement()
+    {
+        $idCriteria = array('source' => $this->article1->id(), 'target' => $this->article2->id());
+
+        $refRep = $this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria);
+
+        $this->_em->remove($refRep);
+        $this->_em->flush();
+        $this->_em->clear();
+
+        $this->assertNull($this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria));
+    }
+
+    /**
+     * @group DDC-117
+     */
+    public function testDqlRemoveCompositeElement()
+    {
+        $idCriteria = array('source' => $this->article1->id(), 'target' => $this->article2->id());
+
+        $dql = "DELETE ".__NAMESPACE__."\DDC117Reference r WHERE r.source = ?1 AND r.target = ?2";
+        $this->_em->createQuery($dql)
+                  ->setParameter(1, $this->article1->id())
+                  ->setParameter(2, $this->article2->id())
+                  ->execute();
+
+        $this->assertNull($this->_em->find(__NAMESPACE__."\DDC117Reference", $idCriteria));
+    }
+
+    /**
+     * @group DDC-117
+     */
+    public function testInverseSideAccess()
+    {
+        $this->article1 = $this->_em->find(__NAMESPACE__."\DDC117Article", $this->article1->id());
+
+        $this->assertEquals(1, count($this->article1->references()));
+        foreach ($this->article1->references() AS $this->reference) {
+            $this->assertType(__NAMESPACE__."\DDC117Reference", $this->reference);
+            $this->assertSame($this->article1, $this->reference->source());
+        }
+
+        $this->_em->clear();
+
+        $dql = 'SELECT a, r FROM '. __NAMESPACE__ . '\DDC117Article a INNER JOIN a.references r WHERE a.id = ?1';
+        $articleDql = $this->_em->createQuery($dql)
+                                ->setParameter(1, $this->article1->id())
+                                ->getSingleResult();
+
+        $this->assertEquals(1, count($this->article1->references()));
+        foreach ($this->article1->references() AS $this->reference) {
+            $this->assertType(__NAMESPACE__."\DDC117Reference", $this->reference);
+            $this->assertSame($this->article1, $this->reference->source());
+        }
+    }
+
+    /**
+     * @group DDC-117
+     */
+    public function testMixedCompositeKey()
+    {
+        $idCriteria = array('article' => $this->article1->id(), 'language' => 'en');
+
+        $this->translation = $this->_em->find(__NAMESPACE__ . '\DDC117Translation', $idCriteria);
+        $this->assertType(__NAMESPACE__ . '\DDC117Translation', $this->translation);
+
+        $this->assertSame($this->translation, $this->_em->find(__NAMESPACE__ . '\DDC117Translation', $idCriteria));
+
+        $this->_em->clear();
+
+        $dql = 'SELECT t, a FROM ' . __NAMESPACE__ . '\DDC117Translation t JOIN t.article a WHERE t.article = ?1 AND t.language = ?2';
+        $dqlTrans = $this->_em->createQuery($dql)
+                              ->setParameter(1, $this->article1->id())
+                              ->setParameter(2, 'en')
+                              ->getSingleResult();
+
+        $this->assertType(__NAMESPACE__ . '\DDC117Translation', $this->translation);
+    }
+
+    /**
+     * @group DDC-117
+     */
+    public function testMixedCompositeKeyViolateUniqueness()
+    {
+        $this->article1 = $this->_em->find(__NAMESPACE__ . '\DDC117Article', $this->article1->id());
+        $this->article1->addTranslation('en', 'Bar');
+        $this->article1->addTranslation('en', 'Baz');
+
+        $this->setExpectedException('Exception');
+        $this->_em->flush();
+    }
+
+    /**
+     * @group DDC-117
+     */
+    public function testOneToOneForeignObjectId()
+    {
+        $this->article1 = new DDC117Article("Foo");
+        $this->_em->persist($this->article1);
+        $this->_em->flush();
+
+        $this->articleDetails = new DDC117ArticleDetails($this->article1, "Very long text");
+        $this->_em->persist($this->articleDetails);
+        $this->_em->flush();
+
+        $this->articleDetails->update("not so very long text!");
+        $this->_em->flush();
+        $this->_em->clear();
+
+        /* @var $article DDC117Article */
+        $article = $this->_em->find(get_class($this->article1), $this->article1->id());
+        $this->assertEquals('not so very long text!', $article->getText());
+    }
+}
+
+/**
+ * @Entity
+ */
+class DDC117Article
+{
+    /** @Id @Column(type="integer", name="article_id") @GeneratedValue */
+    private $id;
+    /** @Column */
+    private $title;
+
+    /**
+     * @OneToMany(targetEntity="DDC117Reference", mappedBy="source")
+     */
+    private $references;
+
+    /**
+     * @OneToOne(targetEntity="DDC117ArticleDetails", mappedBy="article")
+     */
+    private $details;
+
+    /**
+     * @OneToMany(targetEntity="DDC117Translation", mappedBy="article", cascade={"persist"})
+     */
+    private $translations;
+
+    public function __construct($title)
+    {
+        $this->title = $title;
+        $this->references = new \Doctrine\Common\Collections\ArrayCollection();
+        $this->translations = new \Doctrine\Common\Collections\ArrayCollection();
+    }
+
+    public function setDetails($details)
+    {
+        $this->details = $details;
+    }
+
+    public function id()
+    {
+        return $this->id;
+    }
+
+    public function addReference($reference)
+    {
+        $this->references[] = $reference;
+    }
+
+    public function references()
+    {
+        return $this->references;
+    }
+
+    public function addTranslation($language, $title)
+    {
+        $this->translations[] = new DDC117Translation($this, $language, $title);
+    }
+
+    public function getText()
+    {
+        return $this->details->getText();
+    }
+}
+
+/**
+ * @Entity
+ */
+class DDC117ArticleDetails
+{
+    /**
+     * @Id
+     * @OneToOne(targetEntity="DDC117Article", inversedBy="details")
+     * @JoinColumn(name="article_id", referencedColumnName="article_id")
+     */
+    private $article;
+
+    /**
+     * @Column(type="text")
+     */
+    private $text;
+
+    public function __construct($article, $text)
+    {
+        $this->article = $article;
+        $article->setDetails($this);
+
+        $this->update($text);
+    }
+
+    public function update($text)
+    {
+        $this->text = $text;
+    }
+
+    public function getText()
+    {
+        return $this->text;
+    }
+}
+
+/**
+ * @Entity
+ */
+class DDC117Reference
+{
+    /**
+     * @Id
+     * @ManyToOne(targetEntity="DDC117Article", inversedBy="references")
+     * @JoinColumn(name="source_id", referencedColumnName="article_id")
+     */
+    private $source;
+
+    /**
+     * @Id
+     * @ManyToOne(targetEntity="DDC117Article", inversedBy="references")
+     * @JoinColumn(name="target_id", referencedColumnName="article_id")
+     */
+    private $target;
+
+    /**
+     * @column(type="string")
+     */
+    private $description;
+
+    /**
+     * @column(type="datetime")
+     */
+    private $created;
+
+    public function __construct($source, $target, $description)
+    {
+        $source->addReference($this);
+        $target->addReference($this);
+
+        $this->source = $source;
+        $this->target = $target;
+        $this->description = $description;
+        $this->created = new \DateTime("now");
+    }
+
+    public function source()
+    {
+        return $this->source;
+    }
+
+    public function target()
+    {
+        return $this->target;
+    }
+
+    public function setDescription($desc)
+    {
+        $this->description = $desc;
+    }
+
+    public function getDescription()
+    {
+        return $this->description;
+    }
+}
+
+/**
+ * @Entity
+ */
+class DDC117Translation
+{
+    /**
+     * @Id
+     * @ManyToOne(targetEntity="DDC117Article")
+     * @JoinColumn(name="article_id", referencedColumnName="article_id")
+     */
+    private $article;
+
+    /**
+     * @Id @column(type="string")
+     */
+    private $language;
+
+    /**
+     * @column(type="string")
+     */
+    private $title;
+
+    public function __construct($article, $language, $title)
+    {
+        $this->article = $article;
+        $this->language = $language;
+        $this->title = $title;
+    }
+}
\ No newline at end of file
