diff --git entity.install entity.install
index 65cec65..02bf122 100644
--- entity.install
+++ entity.install
@@ -7,6 +7,28 @@
  */
 
 /**
+ * Defines schema fields required for exportable entities.
+ * To be utilized by modules defining exportable entities.
+ */
+function entity_exportable_schema_fields($module_col = 'module', $status_col = 'status') {
+  return array(
+    $module_col => array(
+      'description' => 'The name of the providing module if the entity has been defined in code.',
+      'type' => 'varchar',
+      'length' => 255,
+      'not null' => FALSE,
+    ),
+    $status_col => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => ENTITY_CUSTOM,
+      'size' => 'tiny',
+      'description' => 'The exportable status of the entity.',
+    ),
+  );
+}
+
+/**
  * The entity API modules have been merged into a single module.
  */
 function entity_update_7000() {
diff --git entity.module entity.module
index 83da48f..4da1828 100644
--- entity.module
+++ entity.module
@@ -17,6 +17,16 @@ module_load_include('inc', 'entity', 'includes/entity.property');
 /**
  * A bit flag used to let us know if an entity is in the database.
  */
+
+
+/**
+ * A bit flag used to let us know if an entity has been customly defined.
+ */
+define('ENTITY_CUSTOM', 0x01);
+
+/**
+ * Deprecated, but still here for backward compatibility.
+ */
 define('ENTITY_IN_DB', 0x01);
 
 /**
@@ -35,7 +45,7 @@ define('ENTITY_OVERRIDDEN', 0x03);
  * A bit flag used to mark entities as fixed, thus not changeable for any
  * user.
  */
-define('ENTITY_FIXED', 0x04);
+define('ENTITY_FIXED', 0x04 | 0x02);
 
 
 
@@ -343,7 +353,7 @@ function entity_crud_get_info() {
  * @param $entity
  *   The entity to check the status on.
  * @param $status
- *   The constant status like ENTITY_IN_DB, ENTITY_IN_CODE, ENTITY_OVERRIDDEN
+ *   The constant status like ENTITY_CUSTOM, ENTITY_IN_CODE, ENTITY_OVERRIDDEN
  *   or ENTITY_FIXED.
  *
  * @return
@@ -429,63 +439,145 @@ function entity_var_json_export($var, $prefix = '') {
 }
 
 /**
- * Implements hook_modules_enabled().
+ * Rebuild the default entities provided in code.
+ *
+ * @todo: describe.
  *
- * Invokes hook_entity_enabled() for new default entities.
+ * @param $entity_types
+ *   (optional) If specified, only the defaults of the given entity types are
+ *   rebuilt.
  */
-function entity_modules_enabled($modules) {
-  foreach (entity_crud_get_info() as $entity_type => $info) {
-    if (!empty($info['exportable']) && $entities = _entity_modules_get_defaults($entity_type, $modules)) {
-      module_invoke_all($entity_type . '_enabled', $entities);
-      module_invoke_all('entity_enabled', $entities, $entity_type);
+function entity_defaults_rebuild($entity_types = NULL) {
+  if (isset($entity_types)) {
+    $rebuild = variable_get('entity_defaults_built', array());
+    variable_set('entity_defaults_built', array_diff_key($rebuild, array_flip($entity_types)));
+  }
+  else {
+    variable_set('entity_defaults_built', array());
+  }
+}
+
+/**
+ * Actually rebuild the defaults, triggered by entity_load().
+ */
+function _entity_defaults_rebuild($entity_type) {
+  if (lock_acquire('entity_rebuild_' . $entity_type)) {
+    $built = variable_get('entity_defaults_built', array());
+    $built[$entity_type] = TRUE;
+    variable_set('entity_defaults_built', $built);
+
+    $info = entity_get_info($entity_type);
+    $hook = isset($info['export']['default hook']) ? $info['export']['default hook'] : 'default_' . $entity_type;
+    $keys = $info['entity keys'] + array('module' => 'module', 'status' => 'status', 'name' => $info['entity keys']['id']);
+
+    // Invoke the hook and collect default entities.
+    $entities = array();
+    foreach (module_implements($hook) as $module) {
+      foreach ((array) module_invoke($module, $hook) as $name => $entity) {
+        $entity->{$keys['name']} = $name;
+        $entity->{$keys['module']} = $module;
+        $entities[$name] = $entity;
+      }
+    }
+    drupal_alter($hook, $entities);
+
+    // Remove defaults which are already overridden.
+    $overridden_entities = entity_load($entity_type, array_keys($entities), array($keys['status'] => ENTITY_OVERRIDDEN));
+    $entities = array_diff_key($entities, $overridden_entities);
+
+    // Determine already existing, custom entities and mark them as overridden.
+    $existing_entities = entity_load($entity_type, array_keys($entities), array($keys['status'] => ENTITY_CUSTOM));
+    foreach ($existing_entities as $name => $entity) {
+      $entity->{$keys['status']} |= ENTITY_OVERRIDDEN;
+      $entity->{$keys['module']} = $entities[$name]->{$keys['module']};
+      entity_save($entity_type, $entity);
+    }
+
+    // Save the defaults being not overridden to the db, possible over-writing
+    // previous defaults already saved in the db.
+    foreach (array_diff_key($entities, $existing_entities) as $name => $entity) {
+      $entity->{$keys['status']} |= ENTITY_IN_CODE;
+      // For updating the numeric db identifier has to be set.
+      if ($entity->original = entity_load_unchanged($entity_type, $name)) {
+        $entity->{$keys['id']} = $entity->original->{$keys['id']};
+        unset($entity->is_new);
+      }
+      $entity->is_rebuild = TRUE;
+      entity_save($entity_type, $entity);
     }
+
+    lock_release('entity_rebuild_' . $entity_type);
+  }
+}
+
+/**
+ * Implements hook_modules_enabled().
+ */
+function entity_modules_enabled($modules) {
+  if ($entity_types = _entity_modules_get_default_types($modules)) {
+    entity_defaults_rebuild($entity_types);
   }
 }
 
 /**
  * Implements hook_modules_disabled().
- *
- * Invokes hook_entity_disabled() for new default entities.
  */
 function entity_modules_disabled($modules) {
-  foreach (entity_crud_get_info() as $entity_type => $info) {
-    if (!empty($info['exportable']) && $entities = _entity_modules_get_defaults($entity_type, $modules)) {
-      module_invoke_all($entity_type . '_disabled', $entities);
-      module_invoke_all('entity_disabled', $entities, $entity_type);
-      // Make sure the cache is cleared afterwards, so removed default entities
-      // are not left there.
-      entity_get_controller($entity_type)->resetCache();
+  foreach (_entity_modules_get_default_types($modules) as $entity_type) {
+    $info = entity_get_info($entity_type);
+    $keys = $info['entity keys'] + array('module' => 'module', 'status' => 'status', 'name' => $info['entity keys']['id']);
+    // Remove entities provided in code.
+    $query = new EntityFieldQuery();
+    $query->entityCondition('entity_type', $entity_type, '=')
+          ->propertyCondition($keys['module'], $modules, 'IN')
+          ->propertyCondition($keys['status'], array(ENTITY_IN_CODE, ENTITY_FIXED), 'IN');
+    $result = $query->execute();
+    if (isset($result[$entity_type])) {
+      $entities = entity_load($entity_type, array_keys($result[$entity_type]));
+      entity_delete_multiple($entity_type, array_keys($entities));
     }
-  }
-}
 
-function _entity_modules_get_defaults($entity_type, $modules) {
-  $info = entity_get_info($entity_type);
-  $entities = array();
-  $hook = isset($info['export']['default hook']) ? $info['export']['default hook'] : 'default_' . $entity_type;
-  $module_key = isset($info['entity keys']['module']) ? $info['entity keys']['module'] : 'module';
-  // Collect the ids of all new entities.
-  foreach ($modules as $module) {
-    if (module_hook($module, $hook)) {
-      $result = module_invoke($module, $hook);
-      if ($result && is_array($result)) {
-        $entities += $result;
+    // Update overridden entities to be now custom.
+    $query = new EntityFieldQuery();
+    $query->entityCondition('entity_type', $entity_type, '=')
+          ->propertyCondition($keys['module'], $modules, 'IN')
+          ->propertyCondition($keys['status'], ENTITY_OVERRIDDEN, '=');
+    $result = $query->execute();
+    if (isset($result[$entity_type])) {
+      foreach (entity_load($entity_type, array_keys($result[$entity_type])) as $name => $entity) {
+        $entity->{$keys['status']} = ENTITY_CUSTOM;
+        $entity->{$keys['module']} = NULL;
+        entity_save($entity_type, $entity);
       }
     }
   }
-  if ($ids = array_keys($entities)) {
-    // To make sure the new default entities are retrieved, make sure the cache
-    // is cleared.
-    entity_get_controller($entity_type)->resetCache();
-    // Check whether some of the new entities are already overridden.
-    $entities = array();
-    foreach (entity_load($entity_type, $ids) as $id => $entity) {
-      if (!entity_has_status($entity_type, $entity, ENTITY_OVERRIDDEN)) {
-        $entities[$id] = $entity;
+
+}
+
+/**
+ * Gets all entity types for which defaults are provided by the $modules.
+ */
+function _entity_modules_get_default_types($modules) {
+  $types = array();
+  foreach (entity_crud_get_info() as $entity_type => $info) {
+    if (!empty($info['exportable'])) {
+      $hook = isset($info['export']['default hook']) ? $info['export']['default hook'] : 'default_' . $entity_type;
+      foreach ($modules as $module) {
+        if (module_hook($module, $hook) || module_hook($module, $hook . '_alter')) {
+          $types[] = $entity_type;
+        }
       }
     }
-    return $entities;
   }
+  return $types;
+}
+
+/**
+ * Implements hook_flush_caches().
+ */
+function entity_flush_caches() {
+  entity_property_info_cache_clear();
+  entity_defaults_rebuild();
 }
 
 /**
@@ -528,7 +620,7 @@ function theme_entity_status($variables) {
     $help = t('A module provides this configuration.');
     return $html ? "<span class='entity-status-default' title='$help'>" . $label . "</span>" : $label;
   }
-  elseif ($status & ENTITY_IN_DB) {
+  elseif ($status & ENTITY_CUSTOM) {
     $label = t('Custom');
     $help = t('A custom configuration by a user.');
     return $html ? "<span class='entity-status-custom' title='$help'>" . $label . "</span>" : $label;
diff --git entity.test entity.test
index 3673c37..cb48b5e 100644
--- entity.test
+++ entity.test
@@ -109,7 +109,7 @@ class EntityAPITestCase extends DrupalWebTestCase {
 
     $types = entity_load('entity_test_type', array('test', 'test2'));
     $this->assertEqual($types['test']->label, 'label', 'Default type loaded.');
-    $this->assertTrue($types['test']->status & ENTITY_IN_CODE && !($types['test']->status & ENTITY_IN_DB), 'Default type status is correct.');
+    $this->assertTrue($types['test']->status & ENTITY_IN_CODE && !($types['test']->status & ENTITY_CUSTOM), 'Default type status is correct.');
 
     // Test using a condition, which has to be applied on the defaults.
     $types = entity_load('entity_test_type', FALSE, array('label' => 'label'));
@@ -136,7 +136,18 @@ class EntityAPITestCase extends DrupalWebTestCase {
 
     $types = entity_load('entity_test_type', array('test', 'test2'));
     $this->assertEqual($types['test']->label, 'modified', 'Modified default type loaded by id.');
-    $this->assertTrue($types['test']->status & ENTITY_IN_CODE && $types['test']->status & ENTITY_IN_DB, 'Status of modified type is correct.');
+    $this->assertTrue(entity_has_status('entity_test_type', $types['test'], ENTITY_OVERRIDDEN), 'Status of overridden type is correct.');
+
+    // Test rebuilding the defaults and make sure overridden entities stay.
+    entity_defaults_rebuild();
+    $types = entity_load('entity_test_type', array('test', 'test2'));
+    $this->assertEqual($types['test']->label, 'modified', 'Overridden entity is still overridden.');
+    $this->assertTrue(entity_has_status('entity_test_type', $types['test'], ENTITY_OVERRIDDEN), 'Status of overridden type is correct.');
+
+    // Test reverting.
+    $types['test']->delete();
+    $types = entity_load('entity_test_type', array('test', 'test2'));
+    $this->assertEqual($types['test']->label, 'label', 'Entity has been reverted.');
 
     // Test loading an exportable by its numeric id.
     $result = entity_load('entity_test_type', array($types['test']->id));
@@ -152,17 +163,17 @@ class EntityAPITestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Tests hook_entity_enabled() and hook_entity_disabled().
+   * Make sure insert() and update() hooks for exportables are invoked.
    */
-  function testExportablesActivation() {
+  function testExportableHooks() {
     $_SESSION['entity_hook_test'] = array();
     // Enabling the module should invoke the enabled hook for the other
     // entities provided in code.
     module_enable(array('entity_feature'));
 
-    $all = array('main', 'test', 'test2');
-    $this->assertTrue($_SESSION['entity_hook_test']['entity_enabled'] == array($all), 'Hook entity_enabled has been invoked.');
-    $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_enabled'] == array($all), 'Hook entity_test_type_enabled has been invoked.');
+    $insert = array('main', 'test', 'test2');
+    $this->assertTrue($_SESSION['entity_hook_test']['entity_insert'] == $insert, 'Hook entity_insert has been invoked.');
+    $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_insert'] == $insert, 'Hook entity_test_type_insert has been invoked.');
 
     // Add a new test entity in DB and make sure the hook is invoked too.
     $test3 = entity_create('entity_test_type', array(
@@ -171,35 +182,37 @@ class EntityAPITestCase extends DrupalWebTestCase {
       'weight' => 0,
     ));
     $test3->save();
-    $this->assertTrue($_SESSION['entity_hook_test']['entity_enabled'] == array($all, array('test3')), 'Hook entity_enabled has been invoked.');
-    $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_enabled'] == array($all, array('test3')), 'Hook entity_test_type_enabled has been invoked.');
 
-    // Now override the 'test' entity and make sure it doesn't invoke the
-    // enabling hook as it is already enabled. Then make sure it stays enabled
-    // when the feature module is disabled.
+    $insert[] = 'test3';
+    $this->assertTrue($_SESSION['entity_hook_test']['entity_insert'] == $insert, 'Hook entity_insert has been invoked.');
+    $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_insert'] == $insert, 'Hook entity_test_type_insert has been invoked.');
+
+    // Now override the 'test' entity and make sure it invokes the update hook.
     $result = entity_load('entity_test_type', array('test'));
     $result['test']->label = 'modified';
     $result['test']->save();
 
-    $this->assertTrue($_SESSION['entity_hook_test']['entity_enabled'] == array($all, array('test3')), 'Hook entity_enabled has been invoked.');
-    $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_enabled'] == array($all, array('test3')), 'Hook entity_test_type_enabled has been invoked.');
+    $this->assertTrue($_SESSION['entity_hook_test']['entity_update'] == array('test'), 'Hook entity_update has been invoked.');
+    $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_update'] == array('test'), 'Hook entity_test_type_update has been invoked.');
 
     // 'test' has to remain enabled, as it has been overridden.
-    $all = array('main', 'test2');
+    $delete = array('main', 'test2');
     module_disable(array('entity_feature'));
 
-    $this->assertTrue($_SESSION['entity_hook_test']['entity_disabled'] == array($all), 'Hook entity_disabled has been invoked.');
-    $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_disabled'] == array($all), 'Hook entity_test_type_disabled has been invoked.');
+    $this->assertTrue($_SESSION['entity_hook_test']['entity_delete'] == $delete, 'Hook entity_deleted has been invoked.');
+    $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_delete'] == $delete, 'Hook entity_test_type_deleted has been invoked.');
 
     // Now make sure 'test' is not overridden any more, but custom.
     $result = entity_load('entity_test_type', array('test'));
     $this->assertTrue(!entity_has_status('entity_test_type', $result['test'], ENTITY_OVERRIDDEN), 'Entity is not marked as overridden any more.');
+    $this->assertTrue(entity_has_status('entity_test_type', $result['test'], ENTITY_CUSTOM), 'Entity is marked as custom.');
 
-    // Test disabled hook for deleting the remaining entities from DB.
+    // Test deleting the remaining entities from DB.
     entity_delete_multiple('entity_test_type', array('test', 'test3'));
-    $all2 = array('test', 'test3');
-    $this->assertTrue($_SESSION['entity_hook_test']['entity_disabled'] == array($all, $all2), 'Hook entity_disabled has been invoked.');
-    $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_disabled'] == array($all, $all2), 'Hook entity_test_type_disabled has been invoked.');
+    $delete[] = 'test';
+    $delete[] = 'test3';
+    $this->assertTrue($_SESSION['entity_hook_test']['entity_delete'] == $delete, 'Hook entity_deleted has been invoked.');
+    $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_delete'] == $delete, 'Hook entity_test_type_deleted has been invoked.');
   }
 
   /**
diff --git includes/entity.controller.inc includes/entity.controller.inc
index d7a1b85..f9df6a2 100644
--- includes/entity.controller.inc
+++ includes/entity.controller.inc
@@ -118,8 +118,8 @@ interface EntityAPIControllerInterface extends DrupalEntityControllerInterface {
  */
 class EntityAPIController extends DrupalDefaultEntityController implements EntityAPIControllerInterface {
 
-  protected $defaultEntities, $cacheComplete = FALSE;
-  protected $nameKey, $statusKey, $bundleKey, $moduleKey;
+  protected $cacheComplete = FALSE;
+  protected $nameKey, $statusKey, $bundleKey;
 
   /**
    * Overridden.
@@ -133,9 +133,7 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
     // Use the name key as primary identifier.
     $this->nameKey = isset($this->entityInfo['entity keys']['name']) ? $this->entityInfo['entity keys']['name'] : $this->idKey;
     if (!empty($this->entityInfo['exportable'])) {
-      $this->entityInfo['entity keys'] += array('module' => 'module', 'status' => 'status');
-      $this->statusKey = $this->entityInfo['entity keys']['status'];
-      $this->moduleKey = $this->entityInfo['entity keys']['module'];
+      $this->statusKey = isset($this->entityInfo['entity keys']['status']) ? $this->entityInfo['entity keys']['status'] : 'status';
     }
     // If this is the bundle of another entity, set the bundle key.
     if (isset($this->entityInfo['bundle of'])) {
@@ -181,6 +179,11 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
   public function load($ids = array(), $conditions = array()) {
     $entities = array();
 
+    // For exportable entities, make sure the defaults have been built.
+    if (!empty($this->entityInfo['exportable']) && empty($GLOBALS['conf']['entity_defaults_built'][$this->entityType])) {
+      _entity_defaults_rebuild($this->entityType);
+    }
+
     // Revisions are not statically cached, and require a different query to
     // other conditions, so separate the revision id into its own variable.
     if ($this->revisionKey && isset($conditions[$this->revisionKey])) {
@@ -198,10 +201,6 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
     // database when all requested entities are loaded from cache.
     $passed_ids = !empty($ids) ? array_flip($ids) : FALSE;
 
-    // Add default entities defined in code to the cache.
-    if (!empty($this->entityInfo['exportable']) && !isset($this->defaultEntities)) {
-      $this->getDefaults();
-    }
     // Try to load entities from the static cache.
     if (!$revision_id) {
       $entities = $this->cacheGet($ids, $conditions);
@@ -213,9 +212,8 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
 
     // Load any remaining entities from the database. This is the case if $ids
     // is set to FALSE (so we load all entities), if there are any ids left to
-    // load, if loading a revision, or if $conditions was passed without $ids.
-    if (!$this->cacheComplete && ($ids === FALSE || $ids || $revision_id || ($conditions && !$passed_ids))) {
-      $schema = drupal_get_schema($this->entityInfo['base table']);
+    // load or if loading a revision.
+    if (!$this->cacheComplete && ($ids === FALSE || $ids || $revision_id)) {
       $queried_entities = array();
       foreach ($this->query($ids, $conditions, $revision_id) as $record) {
         // Skip entities already retrieved from cache.
@@ -224,7 +222,7 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
         }
 
         // Care for serialized columns.
-        foreach ($schema['fields'] as $field => $info) {
+        foreach ($this->entityInfo['schema_fields_sql']['base table'] as $field => $info) {
           if (!empty($info['serialize']) && isset($record->$field)) {
             $record->$field = unserialize($record->$field);
             // Support automatic merging of 'data' fields into the entity.
@@ -236,15 +234,7 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
             }
           }
         }
-        if (isset($this->statusKey)) {
-          // Care for setting the status key properly.
-          $record->{$this->statusKey} |= ENTITY_IN_DB;
-          $id = $record->{$this->nameKey};
-          if (isset($this->defaultEntities[$id])) {
-            $record->{$this->statusKey} |= ENTITY_IN_CODE;
-            $record->{$this->moduleKey} = $this->defaultEntities[$id]->{$this->moduleKey};
-          }
-        }
+
         $queried_entities[$record->{$this->nameKey}] = $record;
       }
     }
@@ -279,30 +269,6 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
     return $entities;
   }
 
-  /**
-   * For exportables, incorporate defaults into the cache.
-   */
-  protected function getDefaults() {
-    $this->defaultEntities = array();
-    $hook = isset($this->entityInfo['export']['default hook']) ? $this->entityInfo['export']['default hook'] : 'default_' . $this->entityType;
-    // Invoke the hook and collect default entities.
-    foreach (module_implements($hook) as $module) {
-      foreach ((array) module_invoke($module, $hook) as $id => $entity) {
-        $entity->{$this->statusKey} |= ENTITY_IN_CODE;
-        $entity->{$this->nameKey} = $id;
-        $entity->{$this->moduleKey} = $module;
-        $this->defaultEntities[$id] = $entity;
-      }
-    }
-    drupal_alter($hook, $this->defaultEntities);
-    // Remove any default entities that have been overridden.
-    foreach ($this->query(array_keys($this->defaultEntities), array()) as $record) {
-      $overridden[$record->{$this->nameKey}] = TRUE;
-    }
-    // Handle fetching defaults via the cache.
-    $this->cacheSet(isset($overridden) ? array_diff_key($this->defaultEntities, $overridden) : $this->defaultEntities);
-  }
-
   protected function applyConditions($entities, $conditions = array()) {
     if ($conditions) {
       foreach ($entities as $key => $entity) {
@@ -373,16 +339,8 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
   }
 
   public function resetCache(array $ids = NULL) {
-    unset($this->defaultEntities);
     $this->cacheComplete = FALSE;
-    if (isset($ids)) {
-      foreach ($ids as $id) {
-        unset($this->entityCache[$id]);
-      }
-    }
-    else {
-      $this->entityCache = array();
-    }
+    parent::resetCache($ids);
   }
 
   /**
@@ -392,6 +350,7 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
     if (!empty($this->entityInfo['fieldable']) && function_exists($function = 'field_attach_' . $hook)) {
       $function($this->entityType, $entity);
     }
+
     if (isset($this->entityInfo['bundle of']) && $type = $this->entityInfo['bundle of']) {
       // Call field API bundle attachers for the entity we are a bundle of.
       if ($hook == 'insert') {
@@ -441,14 +400,10 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
 
       foreach ($entities as $id => $entity) {
         $this->invoke('delete', $entity);
-        if (!empty($this->entityInfo['exportable']) && !($entity->{$this->statusKey} & ENTITY_IN_CODE)) {
-          $disabled_entities[$id] = $entity;
+        if (entity_has_status($this->entityType, $entity, ENTITY_IN_CODE)) {
+          $rebuild = TRUE;
         }
       }
-      if (!empty($disabled_entities)) {
-        module_invoke_all($this->entityType . '_disabled', $disabled_entities);
-        module_invoke_all('entity_disabled', $disabled_entities, $this->entityType);
-      }
       // Ignore slave server temporarily.
       db_ignore_slave();
     }
@@ -457,6 +412,13 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
       watchdog_exception($this->entityType, $e);
       throw $e;
     }
+    // We have to postpone rebuilding defaults until the transaction has been
+    // committed. This is as variable_set() triggers a merge query and dies with
+    // a savepoint exception if it is inside a transaction.
+    if (!empty($rebuild)) {
+      $transaction = NULL;
+      entity_defaults_rebuild(array($this->entityType));
+    }
   }
 
   /**
@@ -473,6 +435,10 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
       if (!empty($entity->{$this->nameKey}) && !isset($entity->original)) {
         $entity->original = entity_load_unchanged($this->entityType, $entity->{$this->nameKey});
       }
+      // Update the status for entities getting overridden.
+      if (entity_has_status($this->entityType, $entity, ENTITY_IN_CODE) && empty($entity->is_rebuild)) {
+        $entity->{$this->statusKey} |= ENTITY_CUSTOM;
+      }
 
       $this->invoke('presave', $entity);
 
@@ -484,16 +450,6 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
       else {
         $return = drupal_write_record($this->entityInfo['base table'], $entity);
         $this->invoke('insert', $entity);
-
-        if (!empty($this->entityInfo['exportable'])) {
-          $entity->{$this->statusKey} |= ENTITY_IN_DB;
-          $this->resetCache(array($entity->{$this->nameKey}));
-          if (!entity_has_status($this->entityType, $entity, ENTITY_IN_CODE)) {
-            $entities = array($entity->{$this->nameKey} => $entity);
-            module_invoke_all($this->entityType . '_enabled', $entities);
-            module_invoke_all('entity_enabled', $entities, $this->entityType);
-          }
-        }
       }
       // Ignore slave server temporarily.
       db_ignore_slave();
diff --git tests/entity_test.install tests/entity_test.install
index a879864..43dbd84 100644
--- tests/entity_test.install
+++ tests/entity_test.install
@@ -113,7 +113,7 @@ function entity_test_schema() {
         'description' => 'A serialized array of additional data related to this entity_test type.',
         'merge' => TRUE,
       ),
-    ),
+    ) + entity_exportable_schema_fields(),
     'primary key' => array('id'),
     'unique keys' => array(
       'name' => array('name'),
diff --git tests/entity_test.module tests/entity_test.module
index 2e3d896..6aed96a 100644
--- tests/entity_test.module
+++ tests/entity_test.module
@@ -147,54 +147,62 @@ class EntityClass extends Entity {
 
 
 /**
- * Implements hook_entity_enabled().
+ * Implements hook_entity_insert().
  */
-function entity_test_entity_enabled($entities) {
-  $_SESSION['entity_hook_test']['entity_enabled'][] = array_keys($entities);
+function entity_test_entity_insert($entity, $entity_type) {
+  $_SESSION['entity_hook_test']['entity_insert'][] = entity_id($entity_type, $entity);
 }
 
 /**
- * Implements hook_entity_disabled().
+ * Implements hook_entity_update().
  */
-function entity_test_entity_disabled($entities) {
-  $_SESSION['entity_hook_test']['entity_disabled'][] = array_keys($entities);
+function entity_test_entity_update($entity, $entity_type) {
+  $_SESSION['entity_hook_test']['entity_update'][] = entity_id($entity_type, $entity);
 }
 
 /**
- * Implements hook_entity_test_type_enabled().
+ * Implements hook_entity_delete().
  */
-function entity_test_entity_test_type_enabled($entities) {
-  $_SESSION['entity_hook_test']['entity_test_type_enabled'][] = array_keys($entities);
+function entity_test_entity_delete($entity, $entity_type) {
+  $_SESSION['entity_hook_test']['entity_delete'][] = entity_id($entity_type, $entity);
 }
 
 /**
- * Implements hook_entity_test_type_disabled().
+ * Implements hook_entity_test_type_insert().
  */
-function entity_test_entity_test_type_disabled($entities) {
-  $_SESSION['entity_hook_test']['entity_test_type_disabled'][] = array_keys($entities);
+function entity_test_entity_test_type_insert($entity) {
+  $_SESSION['entity_hook_test']['entity_test_type_insert'][] = $entity->identifier();
 }
 
-
 /**
- * Implements hook_entity_test_type_presave().
+ * Implements hook_entity_test_type_update().
  */
-function entity_test_entity_test_type_presave($entity) {
-  // Determine changes.
+function entity_test_entity_test_type_update($entity) {
+  $_SESSION['entity_hook_test']['entity_test_type_update'][] = $entity->identifier();
+
+  // Determine changes on update.
   if (!empty($entity->original) && $entity->original->label == 'test_changes') {
     if ($entity->original->label != $entity->label) {
-      $entity->label .= '_presave';
+      $entity->label .= '_update';
     }
   }
 }
 
 /**
- * Implements hook_entity_test_type_update().
+ * Implements hook_entity_test_type_delete().
  */
-function entity_test_entity_test_type_update($entity) {
-  // Determine changes on update.
+function entity_test_entity_test_type_delete($entity) {
+  $_SESSION['entity_hook_test']['entity_test_type_delete'][] = $entity->identifier();
+}
+
+/**
+ * Implements hook_entity_test_type_presave().
+ */
+function entity_test_entity_test_type_presave($entity) {
+  // Determine changes.
   if (!empty($entity->original) && $entity->original->label == 'test_changes') {
     if ($entity->original->label != $entity->label) {
-      $entity->label .= '_update';
+      $entity->label .= '_presave';
     }
   }
 }
