diff --git entity/entity.controller.inc entity/entity.controller.inc
index 61f2e53..965eb6e 100644
--- entity/entity.controller.inc
+++ entity/entity.controller.inc
@@ -469,7 +469,13 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
   public function save($entity, DatabaseTransaction $transaction = NULL) {
     $transaction = isset($transaction) ? $transaction : db_transaction();
     try {
+      // Load the stored entity, if any.
+      if (!empty($entity->{$this->nameKey}) && !isset($entity->original)) {
+        $entity->original = entity_load_unchanged($this->entityType, $entity->{$this->nameKey});
+      }
+
       $this->invoke('presave', $entity);
+
       if (!empty($entity->{$this->idKey}) && empty($entity->is_new)) {
         $return = drupal_write_record($this->entityInfo['base table'], $entity, $this->idKey);
         $this->resetCache(array($entity->{$this->nameKey}));
@@ -478,7 +484,7 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
       else {
         $return = drupal_write_record($this->entityInfo['base table'], $entity);
         $this->invoke('insert', $entity);
-        unset($entity->is_new);
+
         if (!empty($this->entityInfo['exportable'])) {
           $entity->{$this->statusKey} |= ENTITY_IN_DB;
           $this->resetCache(array($entity->{$this->nameKey}));
@@ -491,6 +497,8 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
       }
       // Ignore slave server temporarily.
       db_ignore_slave();
+      unset($entity->is_new);
+      unset($entity->original);
 
       return $return;
     }
diff --git entity/entity.test entity/entity.test
index 03b0d0d..9e8cbc5 100644
--- entity/entity.test
+++ entity/entity.test
@@ -79,6 +79,10 @@ class EntityAPITestCase extends DrupalWebTestCase {
     $this->assertEqual($entities[0]->name, 'test', 'Created and loaded entity.');
     $this->assertEqual($entities[1]->name, 'test', 'Created and loaded entity.');
 
+    // Test getting the entity label, which is the used test-type's label.
+    $label = entity_label('entity_test', $entities[0]);
+    $this->assertEqual($label, 'label', 'Default label returned.');
+
     $results = entity_test_load_multiple(array($entity->pid));
     $loaded = array_pop($results);
     $this->assertEqual($loaded->pid, $entity->pid, 'Loaded the entity unrelated to a user.');
@@ -199,6 +203,36 @@ class EntityAPITestCase extends DrupalWebTestCase {
   }
 
   /**
+   * Tests determining changes.
+   */
+  function testChanges() {
+    module_enable(array('entity_feature'));
+    $types = entity_load('entity_test_type');
+
+    // Override the default entity, such it gets saved in the DB.
+    $types['test']->label ='test_changes';
+    $types['test']->save();
+
+    // Now test an update without applying any changes.
+    $types['test']->save();
+    $this->assertEqual($types['test']->label, 'test_changes', 'No changes have been determined.');
+
+    // Apply changes.
+    $types['test']->label = 'updated';
+    $types['test']->save();
+
+    // The hook implementations entity_test_entity_test_type_presave() and
+    // entity_test_entity_test_type_update() determine changes and change the
+    // label.
+    $this->assertEqual($types['test']->label, 'updated_presave_update', 'Changes have been determined.');
+
+    // Test the static load cache to be cleared.
+    $types = entity_load('entity_test_type');
+    $this->assertEqual($types['test']->label, 'updated_presave', 'Static cache has been cleared.');
+  }
+
+
+  /**
    * Tests viewing entites.
    */
   function testRendering() {
diff --git entity/tests/entity_test.module entity/tests/entity_test.module
index e083b2e..2e3d896 100644
--- entity/tests/entity_test.module
+++ entity/tests/entity_test.module
@@ -100,14 +100,6 @@ function entity_test_delete_multiple(array $pids) {
   entity_get_controller('entity_test')->delete($pids);
 }
 
-/**
- * Implement hook_entity_test_type_presave().
- */
-function entity_test_entity_test_type_presave($type) {
-  $data = get_object_vars($type);
-  unset($data['name'], $data['label'], $data['weight'], $data['locked'], $data['data'], $data['status']);
-  $type->data = $data;
-}
 
 /**
  * Main class for test entities.
@@ -132,7 +124,8 @@ class EntityClass extends Entity {
    * Specifies the default label, which is picked up by label() by default.
    */
   protected function defaultLabel() {
-    return "my custom label";
+    $type = entity_test_get_types($this->name);
+    return $type->label;
   }
 
   /**
@@ -180,3 +173,28 @@ function entity_test_entity_test_type_enabled($entities) {
 function entity_test_entity_test_type_disabled($entities) {
   $_SESSION['entity_hook_test']['entity_test_type_disabled'][] = array_keys($entities);
 }
+
+
+/**
+ * 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 .= '_presave';
+    }
+  }
+}
+
+/**
+ * Implements hook_entity_test_type_update().
+ */
+function entity_test_entity_test_type_update($entity) {
+  // Determine changes on update.
+  if (!empty($entity->original) && $entity->original->label == 'test_changes') {
+    if ($entity->original->label != $entity->label) {
+      $entity->label .= '_update';
+    }
+  }
+}
