diff --git a/modules/payment_test/src/Plugin/PluginTest/MockConfigurablePlugin.php b/modules/payment_test/src/Plugin/PluginTest/MockConfigurablePlugin.php
new file mode 100644
index 0000000..1f47741
--- /dev/null
+++ b/modules/payment_test/src/Plugin/PluginTest/MockConfigurablePlugin.php
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment_test\Plugin\PluginTest\MockPlugin.
+ */
+
+namespace Drupal\payment_test\Plugin\PluginTest;
+
+use Drupal\Component\Plugin\ConfigurablePluginInterface;
+use Drupal\Core\Plugin\PluginBase;
+
+/**
+ * Provides a configurable mock plugin.
+ */
+class MockConfigurablePlugin extends PluginBase implements ConfigurablePluginInterface {
+
+  /**
+   * Constructs a Drupal\Component\Plugin\PluginBase object.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition) {
+    $this->configuration = $configuration;
+    $this->pluginId = $plugin_id;
+    $this->pluginDefinition = $plugin_definition;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    return [];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setConfiguration(array $configuration) {
+    $this->configuration = $configuration + $this->defaultConfiguration();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getConfiguration() {
+    return $this->configuration;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function calculateDependencies() {
+    return [];
+  }
+
+}
diff --git a/modules/payment_test/src/Plugin/PluginTest/MockManager.php b/modules/payment_test/src/Plugin/PluginTest/MockManager.php
new file mode 100644
index 0000000..ff0738f
--- /dev/null
+++ b/modules/payment_test/src/Plugin/PluginTest/MockManager.php
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment_test\Plugin\PluginTest\MockManager.
+ */
+
+namespace Drupal\payment_test\Plugin\PluginTest;
+
+use Drupal\Component\Plugin\Factory\DefaultFactory;
+use Drupal\Component\Plugin\PluginManagerBase;
+use Drupal\Component\Plugin\Discovery\StaticDiscovery;
+
+/**
+ * Provides a plugin manager for testing plugni-related functionality.
+ */
+class MockManager extends PluginManagerBase {
+
+  /**
+   * Constructs a new instance.
+   */
+  public function __construct() {
+    $this->discovery = new StaticDiscovery();
+
+    $this->discovery->setDefinition('payment_test_plugin', array(
+      'label' => t('Plugin'),
+      'class' => 'Drupal\payment_test\Plugin\PluginTest\MockPlugin',
+    ));
+
+    $this->discovery->setDefinition('payment_test_configurable_plugin', array(
+      'label' => t('Configurable plugin'),
+      'class' => 'Drupal\payment_test\Plugin\PluginTest\MockConfigurablePlugin',
+    ));
+
+    $this->factory = new DefaultFactory($this->discovery);
+  }
+}
diff --git a/modules/payment_test/src/Plugin/PluginTest/MockPlugin.php b/modules/payment_test/src/Plugin/PluginTest/MockPlugin.php
new file mode 100644
index 0000000..eaefbbf
--- /dev/null
+++ b/modules/payment_test/src/Plugin/PluginTest/MockPlugin.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment_test\Plugin\PluginTest\MockPlugin.
+ */
+
+namespace Drupal\payment_test\Plugin\PluginTest;
+
+use Drupal\Core\Plugin\PluginBase;
+
+/**
+ * Provides a mock plugin.
+ */
+class MockPlugin extends PluginBase {
+
+}
diff --git a/payment.install b/payment.install
index 9e6d0a0..07a382d 100644
--- a/payment.install
+++ b/payment.install
@@ -9,61 +9,6 @@
  * Implements hook_schema().
  */
 function payment_schema() {
-  $schema['payment_line_item'] = array(
-    'fields' => array(
-      'amount' => array(
-        'type' => 'float',
-        'size' => 'big',
-        'not null' => TRUE,
-      ),
-      'amount_total' => array(
-        'type' => 'float',
-        'size' => 'big',
-        'not null' => TRUE,
-      ),
-      'currency_code' => array(
-        'type' => 'varchar',
-        'length' => 3,
-        'not null' => TRUE,
-      ),
-      'name' => array(
-        'type' => 'varchar',
-        'length' => 255,
-      ),
-      'payment_id' => array(
-        'description' => 'The {payment}.id this line item belongs to.',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'plugin_configuration' => array(
-        'type' => 'blob',
-        'not null' => TRUE,
-        'serialize' => TRUE,
-      ),
-      'plugin_id' => array(
-        'type' => 'varchar',
-        'length' => 255,
-      ),
-      'quantity' => array(
-        'type' => 'int',
-        'default' => 1,
-        'not null' => TRUE,
-      ),
-    ),
-    'primary key' => array('name', 'payment_id'),
-    'foreign keys' => array(
-      'payment_id' => array(
-        'table' => 'payment',
-        'columns' => array(
-          'payment_id' => 'id',
-        ),
-      ),
-    ),
-    'indexes' => array(
-      'payment_id' => array('payment_id'),
-    ),
-  );
   $schema['payment_queue'] = array(
     'fields' => array(
       'acquisition_code' => array(
@@ -107,40 +52,6 @@ function payment_schema() {
       'queue_id' => array('queue_id'),
     ),
   );
-  $schema['payment_status'] = array(
-    'fields' => array(
-      'created' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-      ),
-      'payment_id' => array(
-        'description' => 'The payment ID.',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'plugin_id' => array(
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-      ),
-      'id' => array(
-        'type' => 'serial',
-      ),
-    ),
-    'foreign keys' => array(
-      'payment_id' => array(
-        'table' => 'payment',
-        'columns' => array(
-          'payment_id' => 'id',
-        ),
-      ),
-    ),
-    'indexes' => array(
-      'payment_id' => array('payment_id'),
-    ),
-    'primary key' => array('id'),
-  );
 
   return $schema;
 }
diff --git a/src/DatabaseQueue.php b/src/DatabaseQueue.php
index 3158710..95477e1 100644
--- a/src/DatabaseQueue.php
+++ b/src/DatabaseQueue.php
@@ -235,7 +235,7 @@ class DatabaseQueue implements QueueInterface {
     }
     $query = $this->database->select('payment_queue', 'pq');
     $query->addJoin('INNER', 'payment', 'p', 'p.id = pq.payment_id');
-    $query->addJoin('INNER', 'payment_status', 'ps', 'p.last_payment_status_id = ps.id');
+    $query->addJoin('INNER', 'payment_status', 'ps', 'p.last_payment_status_delta = ps.id');
     $query->fields('pq', array('payment_id'))
       ->condition('pq.category_id', $category_id)
       ->condition('ps.plugin_id', $allowed_payment_status_ids)
diff --git a/src/Entity/Payment.php b/src/Entity/Payment.php
index bddb36e..d3ad16e 100644
--- a/src/Entity/Payment.php
+++ b/src/Entity/Payment.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\payment\Entity;
 
-use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface;
 use Drupal\Core\Entity\ContentEntityBase;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
@@ -61,54 +60,6 @@ use Drupal\user\UserInterface;
 class Payment extends ContentEntityBase implements PaymentInterface {
 
   /**
-   * The payment method.
-   *
-   * @var \Drupal\payment\Plugin\Payment\Method\PaymentMethodInterface
-   */
-  protected $method;
-
-  /**
-   * The payment type.
-   *
-   * @var \Drupal\payment\Plugin\Payment\Type\PaymentTypeInterface
-   */
-  protected $type;
-
-  /**
-   * Line items.
-   *
-   * @var \Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemInterface[]
-   *   Keys are line item machine names.
-   */
-  protected $lineItems = [];
-
-  /**
-   * Payment statuses.
-   *
-   * @var array
-   *   Values are \Drupal\payment\Plugin\Payment\Status\PaymentStatusInterface
-   *   objects.
-   */
-  protected $statuses = [];
-
-  /**
-   * {@inheritdoc}
-   */
-  public function __construct(array $values, $entity_type, $bundle = FALSE, $translations = []) {
-    parent::__construct($values, $entity_type, $bundle, $translations);
-    $payment_type_manager = PaymentServiceWrapper::typeManager();
-    if ($payment_type_manager instanceof CachedDiscoveryInterface) {
-      $payment_type_manager->clearCachedDefinitions();
-    }
-    // When a payment is newly created, its bundle is set, but there is no
-    // plugin yet.
-    if (!isset($values['type'])) {
-      $this->type = PaymentServiceWrapper::typeManager()->createInstance($this->bundle());
-    }
-    $this->type->setPayment($this);
-  }
-
-  /**
    * {@inheritdoc}
    */
   public function getChangedTime() {
@@ -126,7 +77,10 @@ class Payment extends ContentEntityBase implements PaymentInterface {
    * {@inheritdoc}
    */
   public function getPaymentType() {
-    return $this->type;
+    /** @var \Drupal\payment\Plugin\Field\FieldType\PluginBagItemInterface $field_item */
+    $field_item = $this->get('payment_type')[0];
+
+    return $field_item->getContainedPluginInstance();
   }
 
   /**
@@ -156,9 +110,7 @@ class Payment extends ContentEntityBase implements PaymentInterface {
    * {@inheritdoc}
    */
   public function setLineItems(array $line_items) {
-    /** @var \Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemInterface[] $line_items */
     foreach ($line_items as $line_item) {
-      $line_item->setPayment($this);
       $this->setLineItem($line_item);
     }
 
@@ -170,7 +122,12 @@ class Payment extends ContentEntityBase implements PaymentInterface {
    */
   public function setLineItem(PaymentLineItemInterface $line_item) {
     $line_item->setPayment($this);
-    $this->lineItems[$line_item->getName()] = $line_item;
+    $line_items = $this->getLineItems();
+    $line_items[] = $line_item;
+    foreach (array_values($line_items) as $delta => $line_item) {
+      $this->get('line_items')[$delta]->setValue($line_item);
+    }
+
 
     return $this;
   }
@@ -179,7 +136,13 @@ class Payment extends ContentEntityBase implements PaymentInterface {
    * {@inheritdoc}
    */
   public function unsetLineItem($name) {
-    unset($this->lineItems[$name]);
+    $line_items = $this->getLineItems();
+    foreach ($line_items as $delta => $line_item) {
+      if ($line_item->getName() == $name) {
+        unset($line_items[$delta]);
+      }
+    }
+    $this->get('line_items')->setValue($line_items);
 
     return $this;
   }
@@ -188,14 +151,30 @@ class Payment extends ContentEntityBase implements PaymentInterface {
    * {@inheritdoc}
    */
   public function getLineItems() {
-    return $this->lineItems;
+    $line_items = [];
+    /** @var \Drupal\payment\Plugin\Field\FieldType\PluginBagItemInterface $field_item */
+    foreach ($this->get('line_items') as $field_item) {
+      /** @var \Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemInterface $line_item */
+      $line_item = $field_item->getContainedPluginInstance();
+      if ($line_item) {
+        $line_items[$line_item->getName()] = $line_item;
+      }
+    }
+
+    return $line_items;
   }
 
   /**
    * {@inheritdoc}
    */
   public function getLineItem($name) {
-    return isset($this->lineItems[$name]) ? $this->lineItems[$name] : NULL;
+    $line_items = $this->getLineItems();
+    foreach ($line_items as $delta => $line_item) {
+      if ($line_item->getName() == $name) {
+        return $line_item;
+      }
+    }
+    return NULL;
   }
 
   /**
@@ -203,9 +182,9 @@ class Payment extends ContentEntityBase implements PaymentInterface {
    */
   public function getLineItemsByType($plugin_id) {
     $line_items = [];
-    foreach ($this->getLineItems() as $line_item) {
+    foreach ($this->getLineItems() as $name => $line_item) {
       if ($line_item->getPluginId() == $plugin_id) {
-        $line_items[$line_item->getName()] = $line_item;
+        $line_items[$name] = $line_item;
       }
     }
 
@@ -217,10 +196,10 @@ class Payment extends ContentEntityBase implements PaymentInterface {
    */
   public function setPaymentStatuses(array $statuses) {
     /** @var \Drupal\payment\Plugin\Payment\Status\PaymentStatusInterface[] $statuses */
-    foreach ($statuses as $status) {
+    foreach (array_values($statuses) as $delta => $status) {
       $status->setPayment($this);
+      $this->get('payment_statuses')[$delta]->setValue($status, FALSE);
     }
-    $this->statuses = array_values($statuses);
 
     return $this;
   }
@@ -228,20 +207,22 @@ class Payment extends ContentEntityBase implements PaymentInterface {
   /**
    * {@inheritdoc}
    */
-  public function setPaymentStatus(PluginPaymentStatusInterface $status, $notify = TRUE) {
+  public function setPaymentStatus(PluginPaymentStatusInterface $status) {
     $previous_status = $this->getPaymentStatus();
     $status->setPayment($this);
     // Prevent duplicate statuses.
     if (!$this->getPaymentStatus() || $this->getPaymentStatus()->getPluginId() != $status->getPluginId()) {
-      $this->statuses[] = $status;
-    }
-    if ($notify) {
-      /** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */
-      $event_dispatcher = \Drupal::service('event_dispatcher');
-      $event = new PaymentStatusSet($this, $previous_status);
-      $event_dispatcher->dispatch(PaymentEvents::PAYMENT_STATUS_SET, $event);
-      // @todo Invoke Rules event.
+      $payment_statuses = $this->getPaymentStatuses();
+      $payment_statuses[] = $status;
+      foreach (array_values($payment_statuses) as $delta => $payment_status) {
+        $this->get('payment_statuses')[$delta]->setValue($payment_status);
+      }
     }
+    /** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */
+    $event_dispatcher = \Drupal::service('event_dispatcher');
+    $event = new PaymentStatusSet($this, $previous_status);
+    $event_dispatcher->dispatch(PaymentEvents::PAYMENT_STATUS_SET, $event);
+    // @todo Invoke Rules event.
 
     return $this;
   }
@@ -250,14 +231,27 @@ class Payment extends ContentEntityBase implements PaymentInterface {
    * {@inheritdoc}
    */
   public function getPaymentStatuses() {
-    return $this->statuses;
+    $payment_statuses = [];
+    /** @var \Drupal\payment\Plugin\Field\FieldType\PluginBagItemInterface $field_item */
+    foreach ($this->get('payment_statuses') as $field_item) {
+      $payment_statuses[] = $field_item->getContainedPluginInstance();
+    }
+
+    return $payment_statuses;
   }
 
   /**
    * {@inheritdoc}
    */
   public function getPaymentStatus() {
-    return $this->statuses ? end($this->statuses) : NULL;
+    $deltas = [];
+    /** @var \Drupal\payment\Plugin\Field\FieldType\PluginBagItemInterface $field_item */
+    foreach ($this->get('payment_statuses') as $delta => $field_item) {
+      $deltas[] = $delta;
+    }
+    $field_item = $this->get('payment_statuses')[max($deltas)];
+
+    return $field_item->getContainedPluginInstance();
   }
 
   /**
@@ -265,7 +259,9 @@ class Payment extends ContentEntityBase implements PaymentInterface {
    */
   public function setPaymentMethod(PluginPaymentMethodInterface $payment_method) {
     $payment_method->setPayment($this);
-    $this->method = $payment_method;
+    /** @var \Drupal\payment\Plugin\Field\FieldType\PluginBagItemInterface $field_item */
+    $field_item = $this->get('payment_method')[0];
+    $field_item->setContainedPluginInstance($payment_method);
 
     return $this;
   }
@@ -274,7 +270,10 @@ class Payment extends ContentEntityBase implements PaymentInterface {
    * {@inheritdoc}
    */
   public function getPaymentMethod() {
-    return $this->method;
+    /** @var \Drupal\payment\Plugin\Field\FieldType\PluginBagItemInterface $field_item */
+    $field_item = $this->get('payment_method')[0];
+
+    return $field_item->getContainedPluginInstance();
   }
 
   /**
@@ -351,39 +350,6 @@ class Payment extends ContentEntityBase implements PaymentInterface {
   /**
    * {@inheritdoc}
    */
-  public static function postLoad(EntityStorageInterface $storage, array &$entities) {
-    /** @var \Drupal\payment\Entity\PaymentInterface[] $entities */
-    foreach ($entities as $payment) {
-      if ($payment->getPaymentMethod()) {
-        $payment->getPaymentMethod()->setPayment($payment);
-      }
-    }
-    /** @var \Drupal\payment\Entity\Payment\PaymentStorageInterface $storage */
-    $storage->loadLineItems($entities);
-    $storage->loadPaymentStatuses($entities);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function postSave(EntityStorageInterface $storage, $update = TRUE) {
-    /** @var \Drupal\payment\Entity\Payment\PaymentStorageInterface $storage */
-    $storage->saveLineItems($this->getLineItems());
-    $storage->savePaymentStatuses($this->getPaymentStatuses());
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function postDelete(EntityStorageInterface $storage, array $entities) {
-    /** @var \Drupal\payment\Entity\Payment\PaymentStorageInterface $storage */
-    $storage->deleteLineItems(array_keys($entities));
-    $storage->deletePaymentStatuses(array_keys($entities));
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
     $fields['bundle'] = BaseFieldDefinition::create('string')
       ->setLabel(t('Payment type'))
@@ -403,6 +369,16 @@ class Payment extends ContentEntityBase implements PaymentInterface {
       ->setSettings(array(
         'target_type' => 'user',
       ));
+    $fields['line_items'] = BaseFieldDefinition::create('payment_plugin_bag')
+      ->setLabel(t('Line items'))
+      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED);
+    $fields['payment_method'] = BaseFieldDefinition::create('payment_plugin_bag')
+      ->setLabel(t('Payment method'));
+    $fields['payment_statuses'] = BaseFieldDefinition::create('payment_plugin_bag')
+      ->setLabel(t('Payment statuses'))
+      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED);
+    $fields['payment_type'] = BaseFieldDefinition::create('payment_plugin_bag')
+      ->setLabel(t('Payment type'));
     $fields['uuid'] = BaseFieldDefinition::create('uuid')
       ->setLabel(t('Universally Unique ID'))
       ->setReadOnly(TRUE);
@@ -410,33 +386,4 @@ class Payment extends ContentEntityBase implements PaymentInterface {
     return $fields;
   }
 
-  /**
-   * Clones the instance.
-   */
-  public function __clone() {
-    parent::__clone();
-    // Clone the payment type.
-    $this->type = clone $this->type;
-    $this->type->setPayment($this);
-
-    // Clone the payment method.
-    if ($this->getPaymentMethod()) {
-      $this->setPaymentMethod(clone $this->getPaymentMethod());
-    }
-
-    // Clone the line items.
-    $cloned_line_items = [];
-    foreach ($this->getLineItems() as $line_item) {
-      $cloned_line_items[] = clone $line_item;
-    }
-    $this->setLineItems($cloned_line_items);
-
-    // Clone the payment statuses.
-    $cloned_statuses = [];
-    foreach ($this->getPaymentStatuses() as $status) {
-      $cloned_statuses[] = clone $status;
-    }
-    $this->setPaymentStatuses($cloned_statuses);
-  }
-
 }
diff --git a/src/Entity/Payment/PaymentStorage.php b/src/Entity/Payment/PaymentStorage.php
index 69fefa2..e5c330d 100644
--- a/src/Entity/Payment/PaymentStorage.php
+++ b/src/Entity/Payment/PaymentStorage.php
@@ -13,8 +13,6 @@ use Drupal\Core\Entity\ContentEntityInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
-use Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemManagerInterface;
-use Drupal\payment\Plugin\Payment\Method\PaymentMethodManagerInterface;
 use Drupal\payment\Plugin\Payment\Status\PaymentStatusManagerInterface;
 use Drupal\payment\Plugin\Payment\Type\PaymentTypeManagerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -22,21 +20,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
 /**
  * Handles storage for payment entities.
  */
-class PaymentStorage extends SqlContentEntityStorage implements PaymentStorageInterface {
-
-  /**
-   * The payment line item manager.
-   *
-   * @var \Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemManagerInterface
-   */
-  protected $paymentLineItemManager;
-
-  /**
-   * The payment method manager.
-   *
-   * @var \Drupal\payment\Plugin\Payment\Method\PaymentMethodManagerInterface
-   */
-  protected $paymentMethodManager;
+class PaymentStorage extends SqlContentEntityStorage {
 
   /**
    * The payment status manager.
@@ -63,19 +47,13 @@ class PaymentStorage extends SqlContentEntityStorage implements PaymentStorageIn
    *   The entity manager.
    * @param \Drupal\Core\Cache\CacheBackendInterface $cache
    *   The entity cache.
-   * @param \Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemManagerInterface $payment_line_item_manager
-   *   The payment line item manager.
-   * @param \Drupal\payment\Plugin\Payment\Method\PaymentMethodManagerInterface $payment_method_manager
-   *   The payment method manager.
    * @param \Drupal\payment\Plugin\Payment\Status\PaymentStatusManagerInterface $payment_status_manager
    *   The payment status manager.
    * @param \Drupal\payment\Plugin\Payment\Type\PaymentTypeManagerInterface $payment_type_manager
    *   The payment type manager.
    */
-  public function __construct(EntityTypeInterface $entity_type, Connection $database, EntityManagerInterface $entity_manager, CacheBackendInterface $cache, PaymentLineItemManagerInterface $payment_line_item_manager, PaymentMethodManagerInterface $payment_method_manager, PaymentStatusManagerInterface $payment_status_manager, PaymentTypeManagerInterface $payment_type_manager) {
+  public function __construct(EntityTypeInterface $entity_type, Connection $database, EntityManagerInterface $entity_manager, CacheBackendInterface $cache, PaymentStatusManagerInterface $payment_status_manager, PaymentTypeManagerInterface $payment_type_manager) {
     parent::__construct($entity_type, $database, $entity_manager, $cache);
-    $this->paymentLineItemManager = $payment_line_item_manager;
-    $this->paymentMethodManager = $payment_method_manager;
     $this->paymentStatusManager = $payment_status_manager;
     $this->paymentTypeManager = $payment_type_manager;
   }
@@ -84,7 +62,7 @@ class PaymentStorage extends SqlContentEntityStorage implements PaymentStorageIn
    * {@inheritdoc}
    */
   public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
-    return new static($entity_type, $container->get('database'), $container->get('entity.manager'), $container->get('cache.entity'), $container->get('plugin.manager.payment.line_item'), $container->get('plugin.manager.payment.method'), $container->get('plugin.manager.payment.status'), $container->get('plugin.manager.payment.type'));
+    return new static($entity_type, $container->get('database'), $container->get('entity.manager'), $container->get('cache.entity'), $container->get('plugin.manager.payment.status'), $container->get('plugin.manager.payment.type'));
   }
 
   /**
@@ -93,6 +71,9 @@ class PaymentStorage extends SqlContentEntityStorage implements PaymentStorageIn
   public function create(array $values = []) {
     /** @var \Drupal\payment\Entity\PaymentInterface $payment */
     $payment = parent::create($values);
+    $payment_type = $this->paymentTypeManager->createInstance($values['bundle']);
+    $payment_type->setPayment($payment);
+    $payment->get('payment_type')->setValue($payment_type);
     $status = $this->paymentStatusManager->createInstance('payment_created')
       ->setCreated(time());
     $payment->setPaymentStatus($status);
@@ -104,6 +85,7 @@ class PaymentStorage extends SqlContentEntityStorage implements PaymentStorageIn
    * {@inheritdoc}
    */
   protected function buildQuery($ids, $revision_id = FALSE) {
+    // @todo  What does this code do?
     $query = $this->database->select('payment', 'payment');
     $query->addTag('payment_load_multiple');
     $query->fields('payment');
@@ -117,159 +99,19 @@ class PaymentStorage extends SqlContentEntityStorage implements PaymentStorageIn
   /**
    * {@inheritdoc}
    */
-  function mapFromStorageRecords(array $records) {
-    foreach ($records as $id => $record) {
-      $payment_method = $record->payment_method_id ? $this->paymentMethodManager->createInstance($record->payment_method_id, unserialize($record->payment_method_configuration)) : NULL;
-      $payment_type = $this->paymentTypeManager->createInstance($record->payment_type_id, unserialize($record->payment_type_configuration));
-      $records[$id] = (object) array(
-        'currency' => $record->currency,
-        'id' => (int) $record->id,
-        'owner' => (int) $record->owner,
-        'method' => $payment_method,
-        'type' => $payment_type,
-        'bundle' => $payment_type->getPluginId(),
-        'uuid' => $record->uuid,
-      );
-    }
-
-    return parent::mapFromStorageRecords($records);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   protected function mapToStorageRecord(ContentEntityInterface $entity, $table_name = NULL) {
     /** @var \Drupal\payment\Entity\PaymentInterface $payment */
     $payment = $entity;
 
-    $record = new \stdClass();
-    $record->bundle = $payment->bundle();
-    $record->currency = $payment->getCurrencyCode();
-    $record->id = $payment->id();
-    $record->first_payment_status_id = current($payment->getPaymentStatuses())->getId();
-    $record->last_payment_status_id = $payment->getPaymentStatus()->getId();
-    $record->owner = $payment->getOwnerId();
-    $record->payment_method_configuration = serialize($payment->getPaymentMethod() ? $payment->getPaymentMethod()->getConfiguration() : []);
-    $record->payment_method_id = $payment->getPaymentMethod() ? $payment->getPaymentMethod()->getPluginId() : NULL;
-    $record->payment_type_configuration = serialize($payment->getPaymentType()->getConfiguration());
-    $record->payment_type_id = $payment->getPaymentType()->getPluginId();
-    $record->uuid = $payment->uuid();
-
-    return $record;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function loadLineItems(array $entities) {
-    /** @var \Drupal\payment\Entity\PaymentInterface[] $entities */
-    $result = $this->database->select('payment_line_item', 'pli')
-      ->fields('pli', array('payment_id', 'plugin_configuration', 'plugin_id'))
-      ->condition('payment_id', array_keys($entities))
-      ->execute();
-    while ($line_item_data = $result->fetchAssoc()) {
-      /** @var \Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemInterface $line_item */
-      $line_item = $this->paymentLineItemManager->createInstance($line_item_data['plugin_id'], unserialize($line_item_data['plugin_configuration']));
-      $line_item->setPayment($entities[$line_item_data['payment_id']]);
-      $entities[$line_item_data['payment_id']]->setLineItem($line_item);
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function saveLineItems(array $line_items) {
-    /** @var \Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemInterface[] $line_items */
-    if ($line_items) {
-      $this->deleteLineItems(array(reset($line_items)->getPayment()->id()));
-      $query = $this->database->insert('payment_line_item')
-        ->fields(array('amount', 'amount_total', 'currency_code', 'name', 'payment_id', 'plugin_configuration', 'plugin_id', 'quantity'));
-      foreach ($line_items as $line_item) {
-        $query->values(array(
-          'amount' => $line_item->getAmount(),
-          'amount_total' => $line_item->getTotalAmount(),
-          'currency_code' => $line_item->getCurrencyCode(),
-          'name' => $line_item->getName(),
-          'payment_id' => $line_item->getPayment()->id(),
-          'plugin_configuration' => serialize($line_item->getConfiguration()),
-          'plugin_id' => $line_item->getPluginId(),
-          'quantity' => $line_item->getQuantity(),
-        ));
-      }
-      $query->execute();
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function deleteLineItems(array $ids) {
-    $this->database->delete('payment_line_item')
-      ->condition('payment_id', $ids)
-      ->execute();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function loadPaymentStatuses(array $entities) {
-    /** @var \Drupal\payment\Entity\PaymentInterface[] $entities */
-    $result = $this->database->select('payment_status', 'ps')
-      ->fields('ps')
-      ->condition('payment_id', array_keys($entities))
-      ->orderBy('id', 'ASC')
-      ->execute();
-    $statuses= array_fill_keys(array_keys($entities), []);
-    while ($status_data = $result->fetchAssoc()) {
-      $status = $this->paymentStatusManager->createInstance($status_data['plugin_id']);
-      $status->setCreated((int) $status_data['created']);
-      $status->setId((int) $status_data['id']);
-      $status->setPayment($entities[$status_data['payment_id']]);
-
-      $statuses[$status->getPayment()->id()][] = $status;
-    }
-    foreach ($entities as $payment) {
-      $payment->setPaymentStatuses($statuses[$payment->id()]);
+    $record = parent::mapToStorageRecord($entity, $table_name);
+    $deltas = [];
+    foreach ($payment->getPaymentStatuses() as $delta => $item) {
+      $deltas[] = $delta;
     }
-  }
+    $record->first_payment_status_delta = min($deltas);
+    $record->last_payment_status_delta = max($deltas);
 
-  /**
-   * {@inheritdoc}
-   */
-  public function savePaymentStatuses(array $statuses) {
-    /** @var \Drupal\payment\Plugin\Payment\Status\PaymentStatusInterface[] $statuses */
-    if ($statuses) {
-      foreach ($statuses as $status) {
-        // Statuses cannot be edited, so only save the ones without an ID.
-        if (!$status->getId()) {
-          $record = array(
-            'created' => $status->getCreated(),
-            'payment_id' => $status->getPayment()->id(),
-            'plugin_id' => $status->getPluginId(),
-          );
-          $id = $this->database->insert('payment_status')
-            ->fields($record)
-            ->execute();
-          $status->setId($id);
-        }
-      }
-      $this->database->update('payment')
-        ->condition('id', reset($statuses)->getPayment()->id())
-        ->fields(array(
-          'first_payment_status_id' => reset($statuses)->getId(),
-          'last_payment_status_id' => end($statuses)->getId(),
-        ))
-        ->execute();
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function deletePaymentStatuses(array $ids) {
-    $this->database->delete('payment_status')
-      ->condition('payment_id', $ids)
-      ->execute();
+    return $record;
   }
 
 }
diff --git a/src/Entity/Payment/PaymentStorageInterface.php b/src/Entity/Payment/PaymentStorageInterface.php
deleted file mode 100644
index 3655ba6..0000000
--- a/src/Entity/Payment/PaymentStorageInterface.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\payment\Entity\Payment\PaymentStorageInterface.
- */
-
-namespace Drupal\payment\Entity\Payment;
-
-use Drupal\Core\Entity\EntityStorageInterface;
-
-/**
- * A storage controller for payment entities.
- */
-interface PaymentStorageInterface extends EntityStorageInterface {
-
-  /**
-   * Loads payment line items.
-   *
-   * @param int[] $ids
-   *   Payment IDs.
-   *
-   * @return array[]
-   *   Keys are payment IDs, values are arrays of which keys are line item names
-   *   and values are \Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemInterface
-   *   objects.
-   */
-  public function loadLineItems(array $ids);
-
-  /**
-   * Saves payment line items.
-   *
-   * @param \Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemInterface[] $line_items
-   */
-  public function saveLineItems(array $line_items);
-
-  /**
-   * Deletes payment line items.
-   *
-   * @param string[] $ids
-   *   Keys are payment IDs. Values are line item names.
-   */
-  public function deleteLineItems(array $ids);
-
-  /**
-   * Loads payment statuses.
-   *
-   * @param int[] $ids
-   *   Payment IDs.
-   *
-   * @return array[]
-   *   Keys are payment IDs, values are arrays of
-   *   \Drupal\payment\Plugin\Payment\Status\PaymentStatusInterface objects.
-   */
-  public function loadPaymentStatuses(array $ids);
-
-  /**
-   * Saves payment statuses.
-   *
-   * @param \Drupal\payment\Plugin\Payment\Status\PaymentStatusInterface[] $statuses
-   */
-  public function savePaymentStatuses(array $statuses);
-
-  /**
-   * Deletes payment statuses.
-   *
-   * @param int[] $ids
-   *   Payment IDs.
-   */
-  public function deletePaymentStatuses(array $ids);
-}
diff --git a/src/Entity/Payment/PaymentStorageSchema.php b/src/Entity/Payment/PaymentStorageSchema.php
index b0b2971..88d8cf5 100644
--- a/src/Entity/Payment/PaymentStorageSchema.php
+++ b/src/Entity/Payment/PaymentStorageSchema.php
@@ -26,54 +26,39 @@ class PaymentStorageSchema extends SqlContentEntityStorageSchema {
   }
 
   /**
+   * Adds non-field columns to the schema.
    *
+   * @param array[] $schema
+   *   The existing schema.
    */
   protected function alterEntitySchemaWithNonFieldColumns(array &$schema) {
     $schema['payment']['fields'] += array(
-      'first_payment_status_id' => array(
-        'description' => "The {payment_status_item}.id of this payment's first status item.",
+      'first_payment_status_delta' => array(
+        'description' => "The {payment__payment_statuses}.delta of this payment's first status item.",
         'type' => 'int',
         'unsigned' => TRUE,
         'default' => 0,
         'not null' => TRUE,
       ),
-      'last_payment_status_id' => array(
-        'description' => "The {payment_status_item}.id of this payment's most recent status item.",
+      'last_payment_status_delta' => array(
+        'description' => "The {payment__payment_statuses}.delta of this payment's most recent status item.",
         'type' => 'int',
         'unsigned' => TRUE,
         'default' => 0,
         'not null' => TRUE,
       ),
-      'payment_method_configuration' => array(
-        'type' => 'blob',
-        'not null' => TRUE,
-        'serialize' => TRUE,
-      ),
-      'payment_method_id' => array(
-        'type' => 'varchar',
-        'length' => 255,
-      ),
-      'payment_type_configuration' => array(
-        'type' => 'blob',
-        'not null' => TRUE,
-        'serialize' => TRUE,
-      ),
-      'payment_type_id' => array(
-        'type' => 'varchar',
-        'length' => 255,
-      ),
     );
     $schema['payment']['foreign keys'] += array(
-      'first_payment_status_id' => array(
-        'table' => 'payment_status_item',
+      'first_payment_status_delta' => array(
+        'table' => 'payment__payment_statuses',
         'columns' => array(
-          'first_payment_status_id' => 'id',
+          'first_payment_status_delta' => 'delta',
         ),
       ),
-      'last_payment_status_id' => array(
-        'table' => 'payment_status_item',
+      'last_payment_status_delta' => array(
+        'table' => 'payment__payment_statuses',
         'columns' => array(
-          'last_payment_status_id' => 'id',
+          'last_payment_status_delta' => 'delta',
         ),
       ),
       'owner' => array(
@@ -83,8 +68,6 @@ class PaymentStorageSchema extends SqlContentEntityStorageSchema {
         ),
       ),
     );
-
-    return $schema;
   }
 
 }
diff --git a/src/Entity/PaymentInterface.php b/src/Entity/PaymentInterface.php
index 10fe99f..1b67197 100644
--- a/src/Entity/PaymentInterface.php
+++ b/src/Entity/PaymentInterface.php
@@ -108,8 +108,7 @@ interface PaymentInterface extends ContentEntityInterface, EntityChangedInterfac
   /**
    * Sets/replaces all statuses without notifications.
    *
-   * @param array $statuses
-   *   \Drupal\payment\Plugin\Payment\Status\PaymentStatusInterface objects.
+   * @param \Drupal\payment\Plugin\Payment\Status\PaymentStatusInterface[] $statuses
    *
    * @return \Drupal\payment\Entity\PaymentInterface
    */
@@ -119,12 +118,10 @@ interface PaymentInterface extends ContentEntityInterface, EntityChangedInterfac
    * Sets a status.
    *
    * @param \Drupal\payment\Plugin\Payment\Status\PaymentStatusInterface $status
-   * @param bool $notify
-   *   Whether or not to trigger a notification event.
    *
    * @return \Drupal\payment\Entity\PaymentInterface
    */
-  public function setPaymentStatus(PluginPaymentStatusInterface $status, $notify = TRUE);
+  public function setPaymentStatus(PluginPaymentStatusInterface $status);
 
   /**
    * Gets all payment statuses.
diff --git a/src/Plugin/DataType/PluginConfiguration.php b/src/Plugin/DataType/PluginConfiguration.php
new file mode 100644
index 0000000..9a9c2e1
--- /dev/null
+++ b/src/Plugin/DataType/PluginConfiguration.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment\Plugin\DataType\PluginConfiguration.
+ */
+
+namespace Drupal\payment\Plugin\DataType;
+
+use Drupal\Component\Plugin\ConfigurablePluginInterface;
+use Drupal\Core\TypedData\TypedData;
+
+/**
+ * Provides a plugin configuration data type.
+ *
+ * @DataType(
+ *   id = "payment_plugin_configuration",
+ *   label = @Translation("Plugin configuration")
+ * )
+ */
+class PluginConfiguration extends TypedData {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getValue() {
+    /** @var \Drupal\payment\Plugin\Field\FieldType\PluginBagItemInterface $parent */
+    $parent = $this->getParent();
+    $plugin_instance = $parent->getContainedPluginInstance();
+
+    return $plugin_instance instanceof ConfigurablePluginInterface ? $plugin_instance->getConfiguration() : [];
+  }
+
+}
diff --git a/src/Plugin/DataType/PluginId.php b/src/Plugin/DataType/PluginId.php
new file mode 100644
index 0000000..642c905
--- /dev/null
+++ b/src/Plugin/DataType/PluginId.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment\Plugin\DataType\PluginId.
+ */
+
+namespace Drupal\payment\Plugin\DataType;
+
+use Drupal\Core\TypedData\Plugin\DataType\String;
+
+/**
+ * Provides a plugin ID data type.
+ *
+ * @DataType(
+ *   id = "payment_plugin_id",
+ *   label = @Translation("Plugin ID")
+ * )
+ */
+class PluginId extends String {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getValue() {
+    /** @var \Drupal\payment\Plugin\Field\FieldType\PluginBagItemInterface $parent */
+    $parent = $this->getParent();
+
+    return $parent->getContainedPluginInstance() ? $parent->getContainedPluginInstance()->getPluginId() : '';
+  }
+
+}
diff --git a/src/Plugin/DataType/PluginInstance.php b/src/Plugin/DataType/PluginInstance.php
new file mode 100644
index 0000000..d303982
--- /dev/null
+++ b/src/Plugin/DataType/PluginInstance.php
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment\Plugin\DataType\PluginInstance.
+ */
+
+namespace Drupal\payment\Plugin\DataType;
+
+use Drupal\Component\Plugin\PluginInspectionInterface;
+use Drupal\Core\TypedData\TypedData;
+
+/**
+ * Provides a plugin instance data type.
+ *
+ * @DataType(
+ *   id = "payment_plugin_instance",
+ *   label = @Translation("Plugin instance")
+ * )
+ */
+class PluginInstance extends TypedData {
+
+  /**
+   * The plugin instance.
+   *
+   * @var \Drupal\Component\Plugin\PluginInspectionInterface
+   */
+  protected $value;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setValue($value, $notify = TRUE) {
+    if (!$value instanceof PluginInspectionInterface) {
+      $value = NULL;
+    }
+    parent::setValue($value, $notify);
+  }
+
+}
diff --git a/src/Plugin/Field/FieldType/PluginBagItem.php b/src/Plugin/Field/FieldType/PluginBagItem.php
new file mode 100644
index 0000000..dab3268
--- /dev/null
+++ b/src/Plugin/Field/FieldType/PluginBagItem.php
@@ -0,0 +1,112 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Field\Plugin\Field\FieldType\PluginBagItem.
+ */
+
+namespace Drupal\payment\Plugin\Field\FieldType;
+
+use Drupal\Component\Plugin\PluginInspectionInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\Field\FieldItemBase;
+use Drupal\Core\TypedData\DataDefinition;
+use Drupal\Core\TypedData\MapDataDefinition;
+
+/**
+ * Provides a field item that contains a plugin instance.
+ *
+ * @FieldType(
+ *   id = "payment_plugin_bag",
+ *   label = @Translation("Plugin instance"),
+ *   list_class = "\Drupal\payment\Plugin\Field\FieldType\PluginBagItemList"
+ * )
+ */
+class PluginBagItem extends FieldItemBase implements PluginBagItemInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContainedPluginInstance() {
+    return $this->get('plugin_instance')->getValue();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setContainedPluginInstance(PluginInspectionInterface $plugin_instance) {
+    $this->get('plugin_instance')->setValue($plugin_instance);
+
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
+    $properties['plugin_id'] = DataDefinition::create('payment_plugin_id')
+      ->setLabel(t('Plugin ID'))
+      ->setComputed(TRUE);
+    $properties['plugin_configuration'] = MapDataDefinition::create('payment_plugin_configuration')
+      ->setLabel(t('Plugin configuration'))
+      ->setComputed(TRUE);
+    $properties['plugin_instance'] = MapDataDefinition::create('payment_plugin_instance')
+      ->setLabel(t('Plugin instance'));
+
+    return $properties;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function mainPropertyName() {
+    return 'plugin_instance';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
+    $columns = array(
+      'plugin_id' => array(
+        'description' => 'The plugin ID.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+      ),
+      'plugin_configuration' => array(
+        'description' => 'The plugin configuration.',
+        'type' => 'blob',
+        'not null' => TRUE,
+        'serialize' => TRUE,
+      ),
+    );
+
+    $schema = array(
+      'columns' => $columns,
+    );
+
+    return $schema;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isEmpty() {
+    return !$this->getContainedPluginInstance();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setValue($values, $notify = TRUE) {
+    if ($values instanceof PluginInspectionInterface) {
+      $values = [
+        'plugin_instance' => $values,
+      ];
+    }
+
+    parent::setValue($values, $notify);
+  }
+
+}
diff --git a/src/Plugin/Field/FieldType/PluginBagItemInterface.php b/src/Plugin/Field/FieldType/PluginBagItemInterface.php
new file mode 100644
index 0000000..c306255
--- /dev/null
+++ b/src/Plugin/Field/FieldType/PluginBagItemInterface.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment\Plugin\Field\FieldType\PluginBagItemInterface.
+ */
+
+namespace Drupal\payment\Plugin\Field\FieldType;
+
+use Drupal\Component\Plugin\PluginInspectionInterface;
+use Drupal\Core\Field\FieldItemInterface;
+
+/**
+ * Defines a plugin bag field item.
+ */
+interface PluginBagItemInterface extends FieldItemInterface {
+
+  /**
+   * Gets the contained plugin instance.
+   *
+   * @return \Drupal\Component\Plugin\PluginInspectionInterface|null
+   *   The plugin or NULL if no plugin was set yet.
+   */
+  public function getContainedPluginInstance();
+
+  /**
+   * Sets the instantiated plugin.
+   *
+   * @param \Drupal\Component\Plugin\PluginInspectionInterface $plugin_instance
+   *
+   * @return $this
+   */
+  public function setContainedPluginInstance(PluginInspectionInterface $plugin_instance);
+
+}
diff --git a/src/Plugin/Field/FieldType/PluginBagItemList.php b/src/Plugin/Field/FieldType/PluginBagItemList.php
new file mode 100644
index 0000000..1b73d7f
--- /dev/null
+++ b/src/Plugin/Field/FieldType/PluginBagItemList.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\payment\Plugin\Field\FieldType\PluginBagItemList.
+ */
+
+namespace Drupal\payment\Plugin\Field\FieldType;
+
+use Drupal\Core\Field\FieldItemList;
+
+/**
+ * Provides a plugin bag field item list.
+ */
+class PluginBagItemList extends FieldItemList {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __clone() {
+    $cloned_items = [];
+    foreach ($this->list as $delta => $item) {
+      $cloned_items[$delta] = clone $item;
+    }
+    $this->list = $cloned_items;
+  }
+
+}
diff --git a/src/Plugin/Payment/LineItem/PaymentLineItemBase.php b/src/Plugin/Payment/LineItem/PaymentLineItemBase.php
index f61d9b5..452b0cd 100644
--- a/src/Plugin/Payment/LineItem/PaymentLineItemBase.php
+++ b/src/Plugin/Payment/LineItem/PaymentLineItemBase.php
@@ -88,7 +88,7 @@ abstract class PaymentLineItemBase extends PluginBase implements PaymentLineItem
    * {@inheritdoc}
    */
   public function setConfiguration(array $configuration) {
-    $this->configuration = $configuration;
+    $this->configuration = $configuration + $this->defaultConfiguration();
   }
 
   /**
diff --git a/src/Plugin/Payment/Method/PaymentMethodBase.php b/src/Plugin/Payment/Method/PaymentMethodBase.php
index 6eb6747..7f36bc9 100644
--- a/src/Plugin/Payment/Method/PaymentMethodBase.php
+++ b/src/Plugin/Payment/Method/PaymentMethodBase.php
@@ -116,7 +116,7 @@ abstract class PaymentMethodBase extends PluginBase implements ContainerFactoryP
    * {@inheritdoc}
    */
   public function setConfiguration(array $configuration) {
-    $this->configuration = $configuration;
+    $this->configuration = $configuration + $this->defaultConfiguration();
   }
 
   /**
diff --git a/src/Plugin/Payment/Method/PaymentMethodInterface.php b/src/Plugin/Payment/Method/PaymentMethodInterface.php
index 3e45743..fa948be 100644
--- a/src/Plugin/Payment/Method/PaymentMethodInterface.php
+++ b/src/Plugin/Payment/Method/PaymentMethodInterface.php
@@ -11,6 +11,7 @@ use Drupal\Component\Plugin\PluginInspectionInterface;
 use Drupal\Core\Plugin\PluginFormInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\payment\Entity\PaymentInterface;
+use Drupal\payment\Plugin\Payment\FieldTypePluginInterface;
 
 /**
  * Defines a payment method.
diff --git a/src/Plugin/Payment/MethodConfiguration/PaymentMethodConfigurationBase.php b/src/Plugin/Payment/MethodConfiguration/PaymentMethodConfigurationBase.php
index 7c245cf..3b25a0b 100644
--- a/src/Plugin/Payment/MethodConfiguration/PaymentMethodConfigurationBase.php
+++ b/src/Plugin/Payment/MethodConfiguration/PaymentMethodConfigurationBase.php
@@ -96,7 +96,7 @@ abstract class PaymentMethodConfigurationBase extends PluginBase implements Paym
    * {@inheritdoc}
    */
   public function setConfiguration(array $configuration) {
-    $this->configuration = $configuration;
+    $this->configuration = $configuration + $this->defaultConfiguration();
   }
 
   /**
diff --git a/src/Plugin/Payment/Status/PaymentStatusBase.php b/src/Plugin/Payment/Status/PaymentStatusBase.php
index 75cb79b..5578e98 100644
--- a/src/Plugin/Payment/Status/PaymentStatusBase.php
+++ b/src/Plugin/Payment/Status/PaymentStatusBase.php
@@ -85,7 +85,7 @@ abstract class PaymentStatusBase extends PluginBase implements ContainerFactoryP
    * {@inheritdoc}
    */
   public function setConfiguration(array $configuration) {
-    $this->configuration = $configuration;
+    $this->configuration = $configuration + $this->defaultConfiguration();
   }
 
   /**
@@ -123,22 +123,6 @@ abstract class PaymentStatusBase extends PluginBase implements ContainerFactoryP
   /**
    * {@inheritdoc}
    */
-  public function setId($id) {
-    $this->configuration['id'] = $id;
-
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getId() {
-    return $this->configuration['id'];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   function getAncestors(){
     return $this->paymentStatusManager->getAncestors($this->getPluginId());
   }
diff --git a/src/Plugin/Payment/Status/PaymentStatusInterface.php b/src/Plugin/Payment/Status/PaymentStatusInterface.php
index 2ba2f9a..7c2f28e 100644
--- a/src/Plugin/Payment/Status/PaymentStatusInterface.php
+++ b/src/Plugin/Payment/Status/PaymentStatusInterface.php
@@ -50,22 +50,6 @@ interface PaymentStatusInterface extends PluginInspectionInterface, Configurable
   public function getPayment();
 
   /**
-   * Sets the ID.
-   *
-   * @param int $id
-   * *
-   * @return static
-   */
-  public function setId($id);
-
-  /**
-   * Gets the ID.
-   *
-   * @return int
-   */
-  public function getId();
-
-  /**
    * Gets this payment status's ancestors.
    *
    * @return array
diff --git a/src/Plugin/Payment/Type/PaymentTypeBase.php b/src/Plugin/Payment/Type/PaymentTypeBase.php
index 664310d..0846f8e 100644
--- a/src/Plugin/Payment/Type/PaymentTypeBase.php
+++ b/src/Plugin/Payment/Type/PaymentTypeBase.php
@@ -83,7 +83,7 @@ abstract class PaymentTypeBase extends PluginBase implements ContainerFactoryPlu
    * {@inheritdoc}
    */
   public function setConfiguration(array $configuration) {
-    $this->configuration = $configuration;
+    $this->configuration = $configuration + $this->defaultConfiguration();
   }
 
   /**
diff --git a/src/Tests/Entity/Payment/PaymentStorageWebTest.php b/src/Tests/Entity/Payment/PaymentStorageWebTest.php
index 39fdc64..3419e43 100644
--- a/src/Tests/Entity/Payment/PaymentStorageWebTest.php
+++ b/src/Tests/Entity/Payment/PaymentStorageWebTest.php
@@ -60,33 +60,17 @@ class PaymentStorageWebTest extends WebTestBase {
     $this->assertTrue(is_numeric($payment->getOwnerId()));
     // Check references to other tables.
     $payment_data = $database->select('payment', 'p')
-      ->fields('p', array('first_payment_status_id', 'last_payment_status_id'))
+      ->fields('p', array('first_payment_status_delta', 'last_payment_status_delta'))
       ->condition('id', $payment->id())
       ->execute()
       ->fetchAssoc();
-    $this->assertEqual($payment_data['first_payment_status_id'], 1);
-    $this->assertEqual($payment_data['last_payment_status_id'], 2);
+    $this->assertEqual($payment_data['first_payment_status_delta'], 0);
+    $this->assertEqual($payment_data['last_payment_status_delta'], 1);
     /** @var \Drupal\payment\Entity\PaymentInterface $payment_loaded */
     $payment_loaded = entity_load_unchanged('payment', $payment->id());
     $this->assertEqual(count($payment_loaded->getLineItems()), count($payment->getLineItems()));
     $this->assertEqual(count($payment_loaded->getPaymentStatuses()), count($payment->getPaymentStatuses()));
-    $this->assertEqual($payment_loaded->getPaymentMethod()->getConfiguration(), $payment_method->getConfiguration());
-    $this->assertEqual($payment_loaded->getPaymentType()->getConfiguration(), $payment_type_configuration);
-
-    // Test deleting a payment.
-    $payment->delete();
-    $this->assertFalse(entity_load('payment', $payment->id()));
-    $line_items_exists = db_select('payment_line_item')
-      ->condition('payment_id', $payment->id())
-      ->countQuery()
-      ->execute()
-      ->fetchField();
-    $this->assertFalse($line_items_exists);
-    $statuses_exist = db_select('payment_status')
-      ->condition('payment_id', $payment->id())
-      ->countQuery()
-      ->execute()
-      ->fetchField();
-    $this->assertFalse($statuses_exist);
+    $this->assertEqual($payment_loaded->getPaymentMethod()->getConfiguration(), $payment->getPaymentMethod()->getConfiguration());
+    $this->assertEqual($payment_loaded->getPaymentType()->getConfiguration(), $payment->getPaymentType()->getConfiguration());
   }
 }
diff --git a/src/Tests/Entity/PaymentUnitTest.php b/src/Tests/Entity/PaymentUnitTest.php
index 14718f2..60039fb 100644
--- a/src/Tests/Entity/PaymentUnitTest.php
+++ b/src/Tests/Entity/PaymentUnitTest.php
@@ -69,7 +69,7 @@ class PaymentUnitTest extends KernelTestBase {
    * Tests getChangedTime().
    */
   protected function testGetChangedTime() {
-    $status = $this->statusManager->createInstance('payment_succes');
+    $status = $this->statusManager->createInstance('payment_success');
     $this->payment->setPaymentStatus($status);
     $this->assertIdentical($this->payment->getChangedTime(), $status->getCreated());
   }
@@ -136,7 +136,7 @@ class PaymentUnitTest extends KernelTestBase {
     $line_item_1->setName($this->randomMachineName());
     $line_item_2 = $this->lineItemManager->createInstance('payment_basic');
     $line_item_2->setName($this->randomMachineName());
-    $this->assertTrue(spl_object_hash($this->payment->setLineItems(array($line_item_1, $line_item_2))), spl_object_hash($this->payment));
+    $this->assertTrue(spl_object_hash($this->payment->setLineItems([$line_item_1, $line_item_2])), spl_object_hash($this->payment));
     $line_items = $this->payment->getLineItems();
     if ($this->assertTrue(is_array($line_items))) {
       $this->assertEqual(spl_object_hash($line_items[$line_item_1->getName()]), spl_object_hash($line_item_1));
@@ -156,23 +156,29 @@ class PaymentUnitTest extends KernelTestBase {
   }
 
   /**
-   * Tests setStatus() and getStatus().
+   * Tests setPaymentStatus() and getPaymentStatus().
    */
-  protected function testGetStatus() {
-    $status = $this->statusManager->createInstance('payment_pending');
-    $this->assertEqual(spl_object_hash($this->payment->setPaymentStatus($status, FALSE)), spl_object_hash($this->payment));
-    $this->assertEqual(spl_object_hash($this->payment->getPaymentStatus()), spl_object_hash($status));
+  protected function testGetPaymentStatus() {
+    $payment_status_a = $this->statusManager->createInstance('payment_pending');
+    $payment_status_b = $this->statusManager->createInstance('payment_failed');
+    $this->assertEqual(spl_object_hash($this->payment->setPaymentStatus($payment_status_a)), spl_object_hash($this->payment));
+    $this->assertEqual(spl_object_hash($this->payment->getPaymentStatus()), spl_object_hash($payment_status_a));
+    // Make sure we always get the last status.
+    $this->payment->setPaymentStatus($payment_status_b);
+    $this->assertEqual(spl_object_hash($this->payment->getPaymentStatus()), spl_object_hash($payment_status_b));
   }
 
   /**
-   * Tests setStatuses() and getStatuses().
+   * Tests setPaymentStatuses() and getPaymentStatuses().
    */
-  protected function testGetStatuses() {
+  protected function testGetPaymentStatuses() {
     $statuses = array($this->statusManager->createInstance('payment_pending'), $this->statusManager->createInstance('payment_failed'));
     $this->assertEqual(spl_object_hash($this->payment->setPaymentStatuses($statuses)), spl_object_hash($this->payment));
     $retrieved_statuses = $this->payment->getPaymentStatuses();
     $this->assertEqual(spl_object_hash(reset($retrieved_statuses)), spl_object_hash(reset($statuses)));
     $this->assertEqual(spl_object_hash(end($retrieved_statuses)), spl_object_hash(end($statuses)));
+    // Make sure we always get the last status.
+    $this->assertEqual(spl_object_hash($this->payment->getPaymentStatus()), spl_object_hash(end($statuses)));
   }
 
   /**
diff --git a/src/Tests/Plugin/Field/FieldType/PluginBagItemTest.php b/src/Tests/Plugin/Field/FieldType/PluginBagItemTest.php
new file mode 100644
index 0000000..135be05
--- /dev/null
+++ b/src/Tests/Plugin/Field/FieldType/PluginBagItemTest.php
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\field\Tests\PluginBagItemTest.
+ */
+
+namespace Drupal\payment\Tests\Plugin\Field\FieldType;
+
+use Drupal\Core\Field\BaseFieldDefinition;
+use Drupal\payment_test\Plugin\PluginTest\MockManager;
+use Drupal\simpletest\KernelTestBase;
+
+/**
+ * Tests \Drupal\payment\Plugin\Field\Plugin\Field\FieldType\PluginBagItemBase.
+ *
+ * @group Payment
+ */
+class PluginBagItemTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['payment', 'payment_test', 'plugin_test'];
+
+  /**
+   * The field item under test.
+   *
+   * @var \Drupal\payment\Plugin\Field\FieldType\PluginBagItem
+   */
+  protected $fieldItem;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $field_definition = BaseFieldDefinition::create('payment_plugin_bag');
+
+    $this->fieldItem = \Drupal::typedDataManager()->create($field_definition)[0];
+  }
+
+  /**
+   * Tests the field.
+   */
+  protected function testField() {
+    $plugin_id = 'payment_test_plugin';
+    $plugin_id_configurable = 'payment_test_configurable_plugin';
+    $plugin_configuration = [
+      'foo' => $this->randomMachineName()
+    ];
+
+    // Test default values.
+    $this->assertEqual($this->fieldItem->get('plugin_id')->getValue(), '');
+    $this->assertEqual($this->fieldItem->get('plugin_configuration')->getValue(), []);
+    $this->assertNull($this->fieldItem->getContainedPluginInstance());
+
+    // Test setting a non-configurable plugin.
+    $plugin_manager = new MockManager();
+    $plugin_instance_nonconfigurable = $plugin_manager->createInstance($plugin_id);
+    $this->fieldItem->setContainedPluginInstance($plugin_instance_nonconfigurable);
+    $this->assertEqual(spl_object_hash($this->fieldItem->getContainedPluginInstance()), spl_object_hash($plugin_instance_nonconfigurable));
+    $this->assertEqual($this->fieldItem->get('plugin_configuration')->getValue(), []);
+
+    // Test setting a configurable plugin.
+    $plugin_manager = new MockManager();
+    /** @var \Drupal\payment_test\Plugin\PluginTest\MockConfigurablePlugin $plugin_instance_configurable */
+    $plugin_instance_configurable = $plugin_manager->createInstance($plugin_id_configurable, $plugin_configuration);
+    $this->fieldItem->setContainedPluginInstance($plugin_instance_configurable);
+    $this->assertEqual(spl_object_hash($this->fieldItem->getContainedPluginInstance()), spl_object_hash($plugin_instance_configurable));
+    $this->assertEqual($this->fieldItem->get('plugin_configuration')->getValue(), $plugin_configuration);
+
+    // Test setting the main property.
+    $this->fieldItem->setValue($plugin_instance_nonconfigurable);
+    $this->assertEqual(spl_object_hash($this->fieldItem->getContainedPluginInstance()), spl_object_hash($plugin_instance_nonconfigurable));
+  }
+
+}
diff --git a/tests/src/Unit/Entity/Payment/PaymentStorageUnitTest.php b/tests/src/Unit/Entity/Payment/PaymentStorageUnitTest.php
index 6b293f3..9e89706 100644
--- a/tests/src/Unit/Entity/Payment/PaymentStorageUnitTest.php
+++ b/tests/src/Unit/Entity/Payment/PaymentStorageUnitTest.php
@@ -47,20 +47,6 @@ class PaymentStorageUnitTest extends UnitTestCase {
   protected $entityType;
 
   /**
-   * The payment line item manager.
-   *
-   * @var \Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemManagerInterface|\PHPUnit_Framework_MockObject_MockObject
-   */
-  protected $paymentLineItemManager;
-
-  /**
-   * The payment method manager.
-   *
-   * @var \Drupal\payment\Plugin\Payment\Method\PaymentMethodManagerInterface|\PHPUnit_Framework_MockObject_MockObject
-   */
-  protected $paymentMethodManager;
-
-  /**
    * The payment status manager.
    *
    * @var \Drupal\payment\Plugin\Payment\Status\PaymentStatusManagerInterface|\PHPUnit_Framework_MockObject_MockObject
@@ -97,15 +83,11 @@ class PaymentStorageUnitTest extends UnitTestCase {
 
     $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
 
-    $this->paymentLineItemManager = $this->getMock('\Drupal\payment\Plugin\Payment\LineItem\PaymentLineItemManagerInterface');
-
-    $this->paymentMethodManager = $this->getMock('\Drupal\payment\Plugin\Payment\Method\PaymentMethodManagerInterface');
-
     $this->paymentStatusManager= $this->getMock('\Drupal\payment\Plugin\Payment\Status\PaymentStatusManagerInterface');
 
     $this->paymentTypeManager = $this->getMock('\Drupal\payment\Plugin\Payment\Type\PaymentTypeManagerInterface');
 
-    $this->storage = new PaymentStorage($this->entityType, $this->database, $this->entityManager, $this->cacheBackend, $this->paymentLineItemManager, $this->paymentMethodManager, $this->paymentStatusManager, $this->paymentTypeManager);
+    $this->storage = new PaymentStorage($this->entityType, $this->database, $this->entityManager, $this->cacheBackend, $this->paymentStatusManager, $this->paymentTypeManager);
   }
 
   /**
@@ -117,8 +99,6 @@ class PaymentStorageUnitTest extends UnitTestCase {
       array('cache.entity', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->cacheBackend),
       array('database', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->database),
       array('entity.manager', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->entityManager),
-      array('plugin.manager.payment.line_item', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->paymentLineItemManager),
-      array('plugin.manager.payment.method', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->paymentMethodManager),
       array('plugin.manager.payment.status', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->paymentStatusManager),
       array('plugin.manager.payment.type', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->paymentTypeManager),
     );
@@ -137,8 +117,8 @@ class PaymentStorageUnitTest extends UnitTestCase {
     $bundle = $this->randomMachineName();
     $currency_code = $this->randomMachineName();
     $id = $this->randomMachineName();
-    $first_payment_status_id = mt_rand();
-    $last_payment_status_id = mt_rand();
+    $first_payment_status_delta = mt_rand();
+    $last_payment_status_delta = mt_rand();
     $owner_id = mt_rand();
     $uuid = $this->randomMachineName();
     $payment_method_id = $this->randomMachineName();
@@ -153,11 +133,11 @@ class PaymentStorageUnitTest extends UnitTestCase {
     $first_payment_status = $this->getMock('\Drupal\payment\Plugin\Payment\Status\PaymentStatusInterface');
     $first_payment_status->expects($this->any())
       ->method('getId')
-      ->will($this->returnValue($first_payment_status_id));
+      ->will($this->returnValue($first_payment_status_delta));
     $last_payment_status = $this->getMock('\Drupal\payment\Plugin\Payment\Status\PaymentStatusInterface');
     $last_payment_status->expects($this->any())
       ->method('getId')
-      ->will($this->returnValue($last_payment_status_id));
+      ->will($this->returnValue($last_payment_status_delta));
 
     $payment_method = $this->getMock('\Drupal\payment\Plugin\Payment\Method\PaymentMethodInterface');
     $payment_method->expects($this->atLeastOnce())
@@ -175,9 +155,7 @@ class PaymentStorageUnitTest extends UnitTestCase {
       ->method('getConfiguration')
       ->will($this->returnValue($payment_type_configuration));
 
-    $payment= $this->getMockBuilder('\Drupal\payment\Entity\Payment')
-      ->disableOriginalConstructor()
-      ->getMock();
+    $payment= $this->getMock('\Drupal\payment\Entity\PaymentInterface');
     $payment->expects($this->atLeastOnce())
       ->method('bundle')
       ->will($this->returnValue($bundle));
@@ -216,8 +194,8 @@ class PaymentStorageUnitTest extends UnitTestCase {
     $this->assertSame($currency_code, $record->currency);
     $this->assertSame($bundle, $record->bundle);
     $this->assertSame($owner_id, $record->owner);
-    $this->assertSame($first_payment_status_id, $record->first_payment_status_id);
-    $this->assertSame($last_payment_status_id, $record->last_payment_status_id);
+    $this->assertSame($first_payment_status_delta, $record->first_payment_status_delta);
+    $this->assertSame($last_payment_status_delta, $record->last_payment_status_delta);
     $this->assertSame($payment_method_id, $record->payment_method_id);
     $this->assertSame(serialize($payment_method_configuration), $record->payment_method_configuration);
     $this->assertSame($payment_type_id, $record->payment_type_id);
diff --git a/tests/src/Unit/Plugin/Payment/Status/PaymentStatusBaseUnitTest.php b/tests/src/Unit/Plugin/Payment/Status/PaymentStatusBaseUnitTest.php
index 0fcdb31..ff36893 100644
--- a/tests/src/Unit/Plugin/Payment/Status/PaymentStatusBaseUnitTest.php
+++ b/tests/src/Unit/Plugin/Payment/Status/PaymentStatusBaseUnitTest.php
@@ -135,16 +135,6 @@ class PaymentStatusBaseUnitTest extends UnitTestCase {
   }
 
   /**
-   * @covers ::setId
-   * @covers ::getId
-   */
-  public function testGetId() {
-    $created = mt_rand();
-    $this->assertSame($this->status, $this->status->setId($created));
-    $this->assertSame($created, $this->status->getId());
-  }
-
-  /**
    * @covers ::getChildren
    */
   public function testGetChildren() {
