diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyTermReferenceItemTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyTermReferenceItemTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f40f858b2bb31a92c57f93218d005d6fe11bbf8d
--- /dev/null
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyTermReferenceItemTest.php
@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\taxonomy\Tests\TaxonomyTermReferenceItemTest.
+ */
+
+namespace Drupal\taxonomy\Tests;
+
+use Drupal\simpletest\WebTestBase;
+use Drupal\taxonomy\Type\TaxonomyTermReferenceItem;
+use Drupal\Core\Entity\Field\FieldItemInterface;
+use Drupal\Core\Entity\Field\FieldInterface;
+
+/**
+ * Tests the new entity API for the taxonomy term reference field type.
+ */
+class TaxonomyTermReferenceItemTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('field', 'field_sql_storage', 'taxonomy', 'entity_test', 'options');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Taxonomy reference API',
+      'description' => 'Tests using entity fields of the taxonomy term reference field type.',
+      'group' => 'Taxonomy',
+    );
+  }
+
+  public function setUp() {
+    parent::setUp();
+    $vocabulary = entity_create('taxonomy_vocabulary', array(
+      'name' => $this->randomName(),
+      'machine_name' => drupal_strtolower($this->randomName()),
+      'langcode' => LANGUAGE_NOT_SPECIFIED,
+    ));
+    $vocabulary->save();
+    $field = array(
+      'field_name' => 'field_test_taxonomy',
+      'type' => 'taxonomy_term_reference',
+      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+      'settings' => array(
+        'allowed_values' => array(
+          array(
+            'vocabulary' => $vocabulary->machine_name,
+            'parent' => 0,
+          ),
+        ),
+      ),
+    );
+    field_create_field($field);
+    $instance = array(
+      'entity_type' => 'entity_test',
+      'field_name' => 'field_test_taxonomy',
+      'bundle' => 'entity_test',
+      'widget' => array(
+        'type' => 'options_select',
+      ),
+    );
+    field_create_instance($instance);
+    $this->term = entity_create('taxonomy_term', array(
+      'name' => $this->randomName(),
+      'vid' => $vocabulary->vid,
+      'langcode' => LANGUAGE_NOT_SPECIFIED,
+    ));
+    $this->term->save();
+  }
+
+  /**
+   * Tests using entity fields of the taxonomy term reference field type.
+   */
+  public function testTaxonomyTermReferenceItem() {
+    $tid = $this->term->id();
+    // Just being able to create the entity like this verifies a lot of code.
+    $entity = entity_create('entity_test', array());
+    $entity->field_test_taxonomy->tid = $this->term->tid;
+    $entity->name->value = $this->randomName();
+    $entity->save();
+
+    $entity = entity_load('entity_test', $entity->id());
+    $this->assertTrue($entity->field_test_taxonomy instanceof FieldInterface, 'Field implements interface.');
+    $this->assertTrue($entity->field_test_taxonomy[0] instanceof FieldItemInterface, 'Field item implements interface.');
+    $this->assertEqual($entity->field_test_taxonomy->tid, $this->term->tid);
+    $this->assertEqual($entity->field_test_taxonomy->entity->name, $this->term->name);
+    $this->assertEqual($entity->field_test_taxonomy->entity->id(), $tid);
+    $this->assertEqual($entity->field_test_taxonomy->entity->uuid(), $this->term->uuid());
+
+    // Change the name of the term via the reference.
+    $new_name = $this->randomName();
+    $entity->field_test_taxonomy->entity->name = $new_name;
+    $entity->field_test_taxonomy->entity->save();
+    // Verify it is the correct name.
+    $term = entity_load('taxonomy_term', $tid);
+    $this->assertEqual($term->name, $new_name);
+
+    // Make sure the computed term reflects updates to the term id.
+    $term2 = entity_create('taxonomy_term', array(
+      'name' => $this->randomName(),
+      'vid' => $this->term->vid,
+      'langcode' => LANGUAGE_NOT_SPECIFIED,
+    ));
+    $term2->save();
+
+    $entity->field_test_taxonomy->tid = $term2->tid;
+    $this->assertEqual($entity->field_test_taxonomy->entity->id(), $term2->tid);
+    $this->assertEqual($entity->field_test_taxonomy->entity->name, $term2->name);
+  }
+
+}
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Type/TaxonomyTermReferenceItem.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Type/TaxonomyTermReferenceItem.php
new file mode 100644
index 0000000000000000000000000000000000000000..8eabe7d6db626ecc61711e83d9d3aa371ca7d854
--- /dev/null
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Type/TaxonomyTermReferenceItem.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\taxonomy\Type\TaxonomyTermReferenceItem.
+ */
+
+namespace Drupal\taxonomy\Type;
+
+use Drupal\Core\Entity\Field\FieldItemBase;
+
+/**
+ * Defines the 'taxonomy_term_reference' entity field item.
+ */
+class TaxonomyTermReferenceItem extends FieldItemBase {
+
+  /**
+   * Property definitions of the contained properties.
+   *
+   * @see self::getPropertyDefinitions()
+   *
+   * @var array
+   */
+  static $propertyDefinitions;
+
+  /**
+   * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions().
+   */
+  public function getPropertyDefinitions() {
+    if (!isset(self::$propertyDefinitions)) {
+      self::$propertyDefinitions['tid'] = array(
+        'type' => 'integer',
+        'label' => t('Referenced taxonomy term id.'),
+      );
+      self::$propertyDefinitions['entity'] = array(
+        'type' => 'entity',
+        'constraints' => array(
+          'entity type' => 'taxonomy_term',
+        ),
+        'label' => t('Term'),
+        'description' => t('The referenced taxonomy term'),
+        // The entity object is computed out of the tid.
+        'computed' => TRUE,
+        'read-only' => FALSE,
+        'settings' => array('id source' => 'tid'),
+      );
+    }
+    return self::$propertyDefinitions;
+  }
+
+  /**
+   * Overrides \Drupal\Core\Entity\Field\FieldItemBase::setValue().
+   */
+  public function setValue($values) {
+    // Treat the values as property value of the entity field, if no array
+    // is given.
+    if (!is_array($values)) {
+      $values = array('entity' => $values);
+    }
+
+    // Entity is computed out of the ID, so we only need to update the ID. Only
+    // set the entity field if no ID is given.
+    if (isset($values['tid'])) {
+      $this->properties['tid']->setValue($values['tid']);
+    }
+    elseif (isset($values['entity'])) {
+      $this->properties['entity']->setValue($values['entity']);
+    }
+    else {
+      $this->properties['entity']->setValue(NULL);
+    }
+    unset($values['entity'], $values['tid']);
+    if ($values) {
+      throw new \InvalidArgumentException('Property ' . key($values) . ' is unknown.');
+    }
+  }
+
+}
diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module
index d8ea5b79c40fbc7a1a49faff26ab5f6ba362478b..0158e7ee446e9b5a74764df782a9b0b3d37ced91 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -1015,6 +1015,7 @@ function taxonomy_field_info() {
       'description' => t('This field stores a reference to a taxonomy term.'),
       'default_widget' => 'options_select',
       'default_formatter' => 'taxonomy_term_reference_link',
+      'field item class' => 'Drupal\taxonomy\Type\TaxonomyTermReferenceItem',
       'settings' => array(
         'allowed_values' => array(
           array(