diff --git a/README.md b/README.md
index 19b42a3..3364b48 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ Currently in development.
 * API for Humans: Type Safety, Immutability & Thread-Safety
 * Convenient builders with compile-time guarantees for required params. Forget about 6-7 `null` in queries
 * Optional Type-Safe Object Mapping, if you don't want to work with `Cursor` and `ContentValues` you don't have to
-* No reflection and no annotations in core, also `StorIO` is not ORM
+* No reflection in Operations and no annotations in the core, also `StorIO` is not ORM
 * Every Operation over `StorIO` can be executed as blocking call or as `rx.Observable`
 * `RxJava` as first class citizen, but it's not required dependency!
 * `rx.Observable` from `Get` Operation **can observe changes** in `StorIO` and receive updates automatically
@@ -129,7 +129,6 @@ StorIOSQLite storIOSQLite = new DefaultStorIOSQLite.Builder()
 ```
 
 You can override Operation Resolver per each individual Operation, it can be useful for working with `SQL JOIN`.
-Also, as you can see, there is no Reflection, and no performance reduction in compare to manual object mapping code.
 
 To **save you from coding boilerplate classes** we created **Annotation Processor** which will generate `PutResolver`, `GetResolver` and `DeleteResolver` at compile time, you just need to use generated classes
 
diff --git a/build.gradle b/build.gradle
index d4665fe..fd6a32b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -60,6 +60,8 @@ ext {
     mockitoCore = 'org.mockito:mockito-core:1.10.19'
     testingSupportLib = 'com.android.support.test:testing-support-lib:0.1'
     guava = 'com.google.guava:guava:18.0'
+    autoParcel = 'com.github.frankiesardo:auto-parcel:0.3'
+    autoParcelProcessor = 'com.github.frankiesardo:auto-parcel-processor:0.3'
 }
 
 // Option to disable Pre-Dexing on CI env
@@ -81,19 +83,4 @@ subprojects {
             project.android.compileOptions.targetCompatibility = JavaVersion.VERSION_1_6
         }
     }
-
-    project.afterEvaluate {
-        // StorIO Sample App uses Dagger's annotations and Java Compiler throws warning:
-        // 'warning: No processor claimed any of these annotations suppress'
-        // Unfortunately this warning can not be ignored
-        // Please feel free to suggest workaround for this problem
-        if (!'storio-sample-app'.equals(project.name)
-                && !'storio-sqlite-annotation'.equals(project.name)
-                && !'storio-sqlite-annotation-processor'.equals(project.name)) {
-            tasks.withType(JavaCompile) {
-                // treat all Java Compiler warnings as errors
-                options.compilerArgs << "-Xlint:all" << "-Werror"
-            }
-        }
-    }
 }
diff --git a/checkstyle/checkstyle.xml b/checkstyle/checkstyle.xml
index dbe8171..dbbdb63 100644
--- a/checkstyle/checkstyle.xml
+++ b/checkstyle/checkstyle.xml
@@ -29,7 +29,7 @@
         <module name="PackageName"/>
         <module name="ParameterName"/>
         <!--<module name="StaticVariableName"/>-->
-        <module name="TypeName"/>
+        <!--<module name="TypeName"/>-->
         <!-- Checks for imports                              -->
         <!-- See http://checkstyle.sf.net/config_import.html -->
         <module name="AvoidStarImport"/>
diff --git a/docs/StorIOSQLite.md b/docs/StorIOSQLite.md
index 52e90e4..e1cd27f 100644
--- a/docs/StorIOSQLite.md
+++ b/docs/StorIOSQLite.md
@@ -260,7 +260,6 @@ StorIOSQLite storIOSQLite = new DefaultStorIOSQLite.Builder()
 ```
 
 You can override Operation Resolver per each individual Operation, it can be useful for working with `SQL JOIN`.
-Also, as you can see, there is no Reflection, and no performance reduction in compare to manual object mapping code.
 
 To **save you from coding boilerplate classes** we created **Annotation Processor** which will generate `PutResolver`, `GetResolver` and `DeleteResolver` at compile time, you just need to use generated classes
 
diff --git a/storio-content-resolver/build.gradle b/storio-content-resolver/build.gradle
index 580d669..3104cda 100644
--- a/storio-content-resolver/build.gradle
+++ b/storio-content-resolver/build.gradle
@@ -17,6 +17,10 @@ android {
     packagingOptions {
         exclude 'LICENSE.txt' // multiple libs have this file -> cause build error
     }
+
+    testOptions {
+        unitTests.returnDefaultValues = true
+    }
 }
 
 dependencies {
diff --git a/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/impl/DefaultStorIOContentResolver.java b/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/impl/DefaultStorIOContentResolver.java
index ba7f8af..0634d54 100644
--- a/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/impl/DefaultStorIOContentResolver.java
+++ b/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/impl/DefaultStorIOContentResolver.java
@@ -20,10 +20,10 @@
 import com.pushtorefresh.storio.contentresolver.query.Query;
 import com.pushtorefresh.storio.contentresolver.query.UpdateQuery;
 
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
 import rx.Observable;
 
@@ -31,6 +31,7 @@
 import static com.pushtorefresh.storio.internal.Environment.throwExceptionIfRxJavaIsNotAvailable;
 import static com.pushtorefresh.storio.internal.Queries.nullableArrayOfStrings;
 import static com.pushtorefresh.storio.internal.Queries.nullableString;
+import static java.util.Collections.unmodifiableMap;
 
 /**
  * Default, thread-safe implementation of {@link StorIOContentResolver}.
@@ -124,7 +125,7 @@ public CompleteBuilder contentResolver(@NonNull ContentResolver contentResolver)
          * @return builder.
          */
         @NonNull
-        public <T> CompleteBuilder addTypeMapping(@NonNull Class<T> type, ContentResolverTypeMapping<T> typeMapping) {
+        public <T> CompleteBuilder addTypeMapping(@NonNull Class<T> type, @NonNull ContentResolverTypeMapping<T> typeMapping) {
             checkNotNull(type, "Please specify type");
             checkNotNull(typeMapping, "Please specify type mapping");
 
@@ -151,24 +152,83 @@ public DefaultStorIOContentResolver build() {
     protected class InternalImpl extends Internal {
 
         @Nullable
-        private final Map<Class<?>, ContentResolverTypeMapping<?>> typesMapping;
+        private final Map<Class<?>, ContentResolverTypeMapping<?>> directTypesMapping;
+
+        @NonNull
+        private final Map<Class<?>, ContentResolverTypeMapping<?>> indirectTypesMappingCache
+                = new ConcurrentHashMap<Class<?>, ContentResolverTypeMapping<?>>();
 
         protected InternalImpl(@Nullable Map<Class<?>, ContentResolverTypeMapping<?>> typesMapping) {
-            this.typesMapping = typesMapping != null
-                    ? Collections.unmodifiableMap(typesMapping)
+            this.directTypesMapping = typesMapping != null
+                    ? unmodifiableMap(typesMapping)
                     : null;
         }
 
         /**
-         * {@inheritDoc}
+         * Gets type mapping for required type.
+         * <p/>
+         * This implementation can handle subclasses of types, that registered its type mapping.
+         * For example: You've added type mapping for {@code User.class},
+         * and you have {@code UserFromServiceA.class} which extends {@code User.class},
+         * and you didn't add type mapping for {@code UserFromServiceA.class}
+         * because they have same fields and you just want to have multiple classes.
+         * This implementation will find type mapping of {@code User.class}
+         * and use it as type mapping for {@code UserFromServiceA.class}.
+         *
+         * @return direct or indirect type mapping for passed type, or {@code null}.
          */
         @SuppressWarnings("unchecked")
         @Nullable
         @Override
         public <T> ContentResolverTypeMapping<T> typeMapping(@NonNull Class<T> type) {
-            return typesMapping != null
-                    ? (ContentResolverTypeMapping<T>) typesMapping.get(type)
-                    : null;
+            if (directTypesMapping == null) {
+                return null;
+            }
+
+            final ContentResolverTypeMapping<T> directTypeMapping = (ContentResolverTypeMapping<T>) directTypesMapping.get(type);
+
+            if (directTypeMapping != null) {
+                // fffast! O(1)
+                return directTypeMapping;
+            } else {
+                // If no direct type mapping found — search for indirect type mapping
+
+                // May be value already in cache.
+                ContentResolverTypeMapping<T> indirectTypeMapping =
+                        (ContentResolverTypeMapping<T>) indirectTypesMappingCache.get(type);
+
+                if (indirectTypeMapping != null) {
+                    // fffast! O(1)
+                    return indirectTypeMapping;
+                }
+
+                // Okay, we don't have direct type mapping.
+                // And we don't have cache for indirect type mapping.
+                // Let's find indirect type mapping and cache it!
+                Class<?> parentType = type.getSuperclass();
+
+                // Search algorithm:
+                // Walk through all parent types of passed type.
+                // If parent type has direct mapping -> we found indirect type mapping!
+                // If current parent type == Object.class -> there is no indirect type mapping.
+                // Complexity:
+                // O(n) where n is number of parent types of passed type (pretty fast).
+
+                // Stop search if root parent is Object.class
+                while (parentType != Object.class) {
+                    indirectTypeMapping = (ContentResolverTypeMapping<T>) directTypesMapping.get(parentType);
+
+                    if (indirectTypeMapping != null) {
+                        indirectTypesMappingCache.put(type, indirectTypeMapping);
+                        return indirectTypeMapping;
+                    }
+
+                    parentType = parentType.getSuperclass();
+                }
+
+                // No indirect type mapping found.
+                return null;
+            }
         }
 
         /**
diff --git a/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/query/DeleteQuery.java b/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/query/DeleteQuery.java
index 96e8e2b..fe017f5 100644
--- a/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/query/DeleteQuery.java
+++ b/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/query/DeleteQuery.java
@@ -129,6 +129,7 @@ public CompleteBuilder uri(@NonNull Uri uri) {
          */
         @NonNull
         public CompleteBuilder uri(@NonNull String uri) {
+            checkNotNull(uri, "Uri should not be null");
             return new CompleteBuilder(Uri.parse(uri));
         }
     }
diff --git a/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/query/InsertQuery.java b/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/query/InsertQuery.java
index 5e621c5..0ecc2b5 100644
--- a/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/query/InsertQuery.java
+++ b/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/query/InsertQuery.java
@@ -85,6 +85,7 @@ public CompleteBuilder uri(@NonNull Uri uri) {
          */
         @NonNull
         public CompleteBuilder uri(@NonNull String uri) {
+            checkNotNull(uri, "Uri should not be null");
             return new CompleteBuilder(Uri.parse(uri));
         }
     }
diff --git a/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/query/Query.java b/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/query/Query.java
index cfdb71f..655af37 100644
--- a/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/query/Query.java
+++ b/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/query/Query.java
@@ -182,6 +182,7 @@ public CompleteBuilder uri(@NonNull Uri uri) {
          */
         @NonNull
         public CompleteBuilder uri(@NonNull String uri) {
+            checkNotNull(uri, "Uri should not be null");
             return new CompleteBuilder(Uri.parse(uri));
         }
     }
diff --git a/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/query/UpdateQuery.java b/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/query/UpdateQuery.java
index 66ef9f6..2b03556 100644
--- a/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/query/UpdateQuery.java
+++ b/storio-content-resolver/src/main/java/com/pushtorefresh/storio/contentresolver/query/UpdateQuery.java
@@ -126,6 +126,7 @@ public CompleteBuilder uri(@NonNull Uri uri) {
          */
         @NonNull
         public CompleteBuilder uri(@NonNull String uri) {
+            checkNotNull(uri, "Uri should not be null");
             return new CompleteBuilder(Uri.parse(uri));
         }
     }
diff --git a/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/impl/DefaultStorIOContentResolverTest.java b/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/impl/DefaultStorIOContentResolverTest.java
new file mode 100644
index 0000000..db7a6c8
--- /dev/null
+++ b/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/impl/DefaultStorIOContentResolverTest.java
@@ -0,0 +1,223 @@
+package com.pushtorefresh.storio.contentresolver.impl;
+
+import android.content.ContentResolver;
+
+import com.pushtorefresh.storio.contentresolver.ContentResolverTypeMapping;
+import com.pushtorefresh.storio.contentresolver.StorIOContentResolver;
+import com.pushtorefresh.storio.contentresolver.operation.delete.DeleteResolver;
+import com.pushtorefresh.storio.contentresolver.operation.get.GetResolver;
+import com.pushtorefresh.storio.contentresolver.operation.put.PutResolver;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.mock;
+
+public class DefaultStorIOContentResolverTest {
+
+    @SuppressWarnings("ConstantConditions")
+    @Test(expected = NullPointerException.class)
+    public void nullContentResolver() {
+        new DefaultStorIOContentResolver.Builder()
+                .contentResolver(null);
+    }
+
+    @SuppressWarnings({"unchecked", "ConstantConditions"})
+    @Test(expected = NullPointerException.class)
+    public void addTypeMappingNullType() {
+        new DefaultStorIOContentResolver.Builder()
+                .contentResolver(mock(ContentResolver.class))
+                .addTypeMapping(null, new ContentResolverTypeMapping.Builder<Object>()
+                        .putResolver(mock(PutResolver.class))
+                        .getResolver(mock(GetResolver.class))
+                        .deleteResolver(mock(DeleteResolver.class))
+                        .build());
+    }
+
+    @SuppressWarnings("ConstantConditions")
+    @Test(expected = NullPointerException.class)
+    public void addTypeMappingNullMapping() {
+        new DefaultStorIOContentResolver.Builder()
+                .contentResolver(mock(ContentResolver.class))
+                .addTypeMapping(Object.class, null);
+    }
+
+    @Test
+    public void shouldReturnNullIfNoTypeMappingsRegistered() {
+        class TestItem {
+
+        }
+
+        final StorIOContentResolver storIOContentResolver = new DefaultStorIOContentResolver.Builder()
+                .contentResolver(mock(ContentResolver.class))
+                .build();
+
+        assertNull(storIOContentResolver.internal().typeMapping(TestItem.class));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void shouldReturnNullIfNotTypeMappingRegisteredForType() {
+        class TestItem {
+
+        }
+
+        class Entity {
+
+        }
+
+        final ContentResolverTypeMapping<Entity> entityContentResolverTypeMapping = new ContentResolverTypeMapping.Builder<Entity>()
+                .putResolver(mock(PutResolver.class))
+                .getResolver(mock(GetResolver.class))
+                .deleteResolver(mock(DeleteResolver.class))
+                .build();
+
+        final StorIOContentResolver storIOContentResolver = new DefaultStorIOContentResolver.Builder()
+                .contentResolver(mock(ContentResolver.class))
+                .addTypeMapping(Entity.class, entityContentResolverTypeMapping)
+                .build();
+
+        assertSame(entityContentResolverTypeMapping, storIOContentResolver.internal().typeMapping(Entity.class));
+
+        assertNull(storIOContentResolver.internal().typeMapping(TestItem.class));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void directTypeMappingShouldWork() {
+        class TestItem {
+
+        }
+
+        final ContentResolverTypeMapping<TestItem> typeMapping = new ContentResolverTypeMapping.Builder<TestItem>()
+                .putResolver(mock(PutResolver.class))
+                .getResolver(mock(GetResolver.class))
+                .deleteResolver(mock(DeleteResolver.class))
+                .build();
+
+        final StorIOContentResolver storIOContentResolver = new DefaultStorIOContentResolver.Builder()
+                .contentResolver(mock(ContentResolver.class))
+                .addTypeMapping(TestItem.class, typeMapping)
+                .build();
+
+        assertSame(typeMapping, storIOContentResolver.internal().typeMapping(TestItem.class));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void indirectTypeMappingShouldWork() {
+        class TestItem {
+
+        }
+
+        final ContentResolverTypeMapping<TestItem> typeMapping = new ContentResolverTypeMapping.Builder<TestItem>()
+                .putResolver(mock(PutResolver.class))
+                .getResolver(mock(GetResolver.class))
+                .deleteResolver(mock(DeleteResolver.class))
+                .build();
+
+        final StorIOContentResolver storIOContentResolver = new DefaultStorIOContentResolver.Builder()
+                .contentResolver(mock(ContentResolver.class))
+                .addTypeMapping(TestItem.class, typeMapping)
+                .build();
+
+        class TestItemSubclass extends TestItem {
+
+        }
+
+        // Direct type mapping should still work
+        assertSame(typeMapping, storIOContentResolver.internal().typeMapping(TestItem.class));
+
+        // Indirect type mapping should give same type mapping as for parent class
+        assertSame(typeMapping, storIOContentResolver.internal().typeMapping(TestItemSubclass.class));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void typeMappingShouldWorkInCaseOfMoreConcreteTypeMapping() {
+        class TestItem {
+
+        }
+
+        final ContentResolverTypeMapping<TestItem> typeMapping = new ContentResolverTypeMapping.Builder<TestItem>()
+                .putResolver(mock(PutResolver.class))
+                .getResolver(mock(GetResolver.class))
+                .deleteResolver(mock(DeleteResolver.class))
+                .build();
+
+        class TestItemSubclass extends TestItem {
+
+        }
+
+        final ContentResolverTypeMapping<TestItemSubclass> subclassTypeMapping = new ContentResolverTypeMapping.Builder<TestItemSubclass>()
+                .putResolver(mock(PutResolver.class))
+                .getResolver(mock(GetResolver.class))
+                .deleteResolver(mock(DeleteResolver.class))
+                .build();
+
+        final StorIOContentResolver storIOContentResolver = new DefaultStorIOContentResolver.Builder()
+                .contentResolver(mock(ContentResolver.class))
+                .addTypeMapping(TestItem.class, typeMapping)
+                .addTypeMapping(TestItemSubclass.class, subclassTypeMapping)
+                .build();
+
+        // Parent class should have its own type mapping
+        assertSame(typeMapping, storIOContentResolver.internal().typeMapping(TestItem.class));
+
+        // Child class should have its own type mapping
+        assertSame(subclassTypeMapping, storIOContentResolver.internal().typeMapping(TestItemSubclass.class));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void typeMappingShouldFindIndirectTypeMappingInCaseOfComplexInheritance() {
+        // Good test case — inheritance with AutoValue/AutoParcel
+
+        class Entity {
+
+        }
+
+        class AutoValue_Entity extends Entity {
+
+        }
+
+        class ConcreteEntity extends Entity {
+
+        }
+
+        class AutoValue_ConcreteEntity extends ConcreteEntity {
+
+        }
+
+        final ContentResolverTypeMapping<Entity> entitySQLiteTypeMapping = new ContentResolverTypeMapping.Builder<Entity>()
+                .putResolver(mock(PutResolver.class))
+                .getResolver(mock(GetResolver.class))
+                .deleteResolver(mock(DeleteResolver.class))
+                .build();
+
+        final ContentResolverTypeMapping<ConcreteEntity> concreteEntitySQLiteTypeMapping = new ContentResolverTypeMapping.Builder<ConcreteEntity>()
+                .putResolver(mock(PutResolver.class))
+                .getResolver(mock(GetResolver.class))
+                .deleteResolver(mock(DeleteResolver.class))
+                .build();
+
+        final StorIOContentResolver storIOContentResolver = new DefaultStorIOContentResolver.Builder()
+                .contentResolver(mock(ContentResolver.class))
+                .addTypeMapping(Entity.class, entitySQLiteTypeMapping)
+                .addTypeMapping(ConcreteEntity.class, concreteEntitySQLiteTypeMapping)
+                .build();
+
+        // Direct type mapping for Entity should work
+        assertSame(entitySQLiteTypeMapping, storIOContentResolver.internal().typeMapping(Entity.class));
+
+        // Direct type mapping for ConcreteEntity should work
+        assertSame(concreteEntitySQLiteTypeMapping, storIOContentResolver.internal().typeMapping(ConcreteEntity.class));
+
+        // Indirect type mapping for AutoValue_Entity should get type mapping for Entity
+        assertSame(entitySQLiteTypeMapping, storIOContentResolver.internal().typeMapping(AutoValue_Entity.class));
+
+        // Indirect type mapping for AutoValue_ConcreteEntity should get type mapping for ConcreteEntity, not for Entity!
+        assertSame(concreteEntitySQLiteTypeMapping, storIOContentResolver.internal().typeMapping(AutoValue_ConcreteEntity.class));
+    }
+}
diff --git a/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/query/DeleteQueryTest.java b/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/query/DeleteQueryTest.java
index f66358c..9907deb 100644
--- a/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/query/DeleteQueryTest.java
+++ b/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/query/DeleteQueryTest.java
@@ -22,7 +22,7 @@ public void shouldNotAllowNullUriObject() {
     }
 
     @SuppressWarnings("ConstantConditions")
-    @Test(expected = RuntimeException.class) // Uri#parse() not mocked
+    @Test(expected = NullPointerException.class) // Uri#parse() not mocked
     public void shouldNotAllowNullUriString() {
         new DeleteQuery.Builder()
                 .uri((String) null)
diff --git a/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/query/InsertQueryTest.java b/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/query/InsertQueryTest.java
index 1a957d4..9ddfd4f 100644
--- a/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/query/InsertQueryTest.java
+++ b/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/query/InsertQueryTest.java
@@ -18,7 +18,7 @@ public void shouldNotAllowNullUriObject() {
     }
 
     @SuppressWarnings("ConstantConditions")
-    @Test(expected = RuntimeException.class)
+    @Test(expected = NullPointerException.class)
     public void shouldNotAllowNullUriString() {
         new InsertQuery.Builder()
                 .uri((String) null)
diff --git a/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/query/QueryTest.java b/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/query/QueryTest.java
index 89fd1ce..37c05c4 100644
--- a/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/query/QueryTest.java
+++ b/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/query/QueryTest.java
@@ -21,7 +21,7 @@ public void shouldNotAllowNullUriObject() {
     }
 
     @SuppressWarnings("ConstantConditions")
-    @Test(expected = RuntimeException.class)
+    @Test(expected = NullPointerException.class)
     public void shouldNotAllowNullUriString() {
         new Query.Builder()
                 .uri((String) null)
diff --git a/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/query/UpdateQueryTest.java b/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/query/UpdateQueryTest.java
index fd35f9e..7898bb4 100644
--- a/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/query/UpdateQueryTest.java
+++ b/storio-content-resolver/src/test/java/com/pushtorefresh/storio/contentresolver/query/UpdateQueryTest.java
@@ -21,7 +21,7 @@ public void shouldNotAllowNullUriObject() {
     }
 
     @SuppressWarnings("ConstantConditions")
-    @Test(expected = RuntimeException.class)
+    @Test(expected = NullPointerException.class)
     public void shouldNotAllowNullUriString() {
         new UpdateQuery.Builder()
                 .uri((String) null)
diff --git a/storio-sqlite/build.gradle b/storio-sqlite/build.gradle
index 7a6f771..259bbaf 100644
--- a/storio-sqlite/build.gradle
+++ b/storio-sqlite/build.gradle
@@ -1,6 +1,7 @@
 apply plugin: 'android-sdk-manager'
 apply plugin: 'com.android.library'
 apply plugin: 'checkstyle'
+apply plugin: 'com.neenbedankt.android-apt'
 
 android {
     compileSdkVersion rootProject.ext.compileSdkVersion
@@ -32,6 +33,8 @@ dependencies {
 
     androidTestCompile project(':storio-test-common')
     androidTestCompile rootProject.ext.testingSupportLib
+    androidTestCompile rootProject.ext.autoParcel
+    androidTestApt     rootProject.ext.autoParcelProcessor
 }
 
 task checkstyle(type: Checkstyle) {
diff --git a/storio-sqlite/src/androidTest/java/com/pushtorefresh/storio/sqlite/impl/UserTableMeta.java b/storio-sqlite/src/androidTest/java/com/pushtorefresh/storio/sqlite/impl/UserTableMeta.java
index 40474e8..8c4b225 100644
--- a/storio-sqlite/src/androidTest/java/com/pushtorefresh/storio/sqlite/impl/UserTableMeta.java
+++ b/storio-sqlite/src/androidTest/java/com/pushtorefresh/storio/sqlite/impl/UserTableMeta.java
@@ -23,17 +23,21 @@
     static final String TABLE = "users";
     static final String COLUMN_ID = "_id";
     static final String COLUMN_EMAIL = "email";
+
     // We all will be very old when Java will support string interpolation :(
     static final String SQL_CREATE_TABLE = "CREATE TABLE " + TABLE + "(" +
             COLUMN_ID + " INTEGER PRIMARY KEY, " +
             COLUMN_EMAIL + " TEXT NOT NULL" +
             ");";
+
     static final Query QUERY_ALL = new Query.Builder()
             .table(TABLE)
             .build();
+
     static final DeleteQuery DELETE_QUERY_ALL = new DeleteQuery.Builder()
             .table(TABLE)
             .build();
+
     static final PutResolver<User> PUT_RESOLVER = new DefaultPutResolver<User>() {
         @NonNull
         @Override
diff --git a/storio-sqlite/src/androidTest/java/com/pushtorefresh/storio/sqlite/impl/auto_parcel/AutoParcelTest.java b/storio-sqlite/src/androidTest/java/com/pushtorefresh/storio/sqlite/impl/auto_parcel/AutoParcelTest.java
new file mode 100644
index 0000000..07358c7
--- /dev/null
+++ b/storio-sqlite/src/androidTest/java/com/pushtorefresh/storio/sqlite/impl/auto_parcel/AutoParcelTest.java
@@ -0,0 +1,160 @@
+package com.pushtorefresh.storio.sqlite.impl.auto_parcel;
+
+import android.support.annotation.NonNull;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping;
+import com.pushtorefresh.storio.sqlite.StorIOSQLite;
+import com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite;
+import com.pushtorefresh.storio.sqlite.operation.delete.DeleteResult;
+import com.pushtorefresh.storio.sqlite.operation.put.PutResult;
+import com.pushtorefresh.storio.sqlite.query.DeleteQuery;
+import com.pushtorefresh.storio.sqlite.query.Query;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(AndroidJUnit4.class)
+public class AutoParcelTest {
+
+    @NonNull // Initialized in @Before
+    private StorIOSQLite storIOSQLite;
+
+    @Before
+    public void setUp() {
+        storIOSQLite = new DefaultStorIOSQLite.Builder()
+                .sqliteOpenHelper(new OpenHelper(InstrumentationRegistry.getContext()))
+                .addTypeMapping(Book.class, new SQLiteTypeMapping.Builder<Book>()
+                        .putResolver(BookTableMeta.PUT_RESOLVER)
+                        .getResolver(BookTableMeta.GET_RESOLVER)
+                        .deleteResolver(BookTableMeta.DELETE_RESOLVER)
+                        .build())
+                .build();
+
+        // Clearing books table before each test case
+        storIOSQLite
+                .delete()
+                .byQuery(new DeleteQuery.Builder()
+                        .table(BookTableMeta.TABLE)
+                        .build())
+                .prepare()
+                .executeAsBlocking();
+    }
+
+    @Test
+    public void insertObject() {
+        final Book book = Book.builder()
+                .id(1)
+                .title("What a great book")
+                .author("Somebody")
+                .build();
+
+        final PutResult putResult = storIOSQLite
+                .put()
+                .object(book)
+                .prepare()
+                .executeAsBlocking();
+
+        assertTrue(putResult.wasInserted());
+
+        final List<Book> storedBooks = storIOSQLite
+                .get()
+                .listOfObjects(Book.class)
+                .withQuery(new Query.Builder()
+                        .table(BookTableMeta.TABLE)
+                        .build())
+                .prepare()
+                .executeAsBlocking();
+
+        assertEquals(1, storedBooks.size());
+
+        assertEquals(book, storedBooks.get(0));
+    }
+
+    @Test
+    public void updateObject() {
+        final Book book = Book.builder()
+                .id(1)
+                .title("What a great book")
+                .author("Somebody")
+                .build();
+
+        final PutResult putResult1 = storIOSQLite
+                .put()
+                .object(book)
+                .prepare()
+                .executeAsBlocking();
+
+        assertTrue(putResult1.wasInserted());
+
+        final Book bookWithUpdatedInfo = Book.builder()
+                .id(1) // Same id, should be updated
+                .title("Corrected title")
+                .author("Corrected author")
+                .build();
+
+        final PutResult putResult2 = storIOSQLite
+                .put()
+                .object(bookWithUpdatedInfo)
+                .prepare()
+                .executeAsBlocking();
+
+        assertTrue(putResult2.wasUpdated());
+
+        final List<Book> storedBooks = storIOSQLite
+                .get()
+                .listOfObjects(Book.class)
+                .withQuery(new Query.Builder()
+                        .table(BookTableMeta.TABLE)
+                        .build())
+                .prepare()
+                .executeAsBlocking();
+
+        assertEquals(1, storedBooks.size());
+
+        assertEquals(bookWithUpdatedInfo, storedBooks.get(0));
+    }
+
+    @Test
+    public void deleteObject() {
+        final Book book = Book.builder()
+                .id(1)
+                .title("What a great book")
+                .author("Somebody")
+                .build();
+
+        final PutResult putResult = storIOSQLite
+                .put()
+                .object(book)
+                .prepare()
+                .executeAsBlocking();
+
+        assertTrue(putResult.wasInserted());
+
+        final DeleteResult deleteResult = storIOSQLite
+                .delete()
+                .object(book)
+                .prepare()
+                .executeAsBlocking();
+
+        assertEquals(1, deleteResult.numberOfRowsDeleted());
+
+        final List<Book> storedBooks = storIOSQLite
+                .get()
+                .listOfObjects(Book.class)
+                .withQuery(new Query.Builder()
+                        .table(BookTableMeta.TABLE)
+                        .build())
+                .prepare()
+                .executeAsBlocking();
+
+        assertEquals(0, storedBooks.size());
+    }
+}
diff --git a/storio-sqlite/src/androidTest/java/com/pushtorefresh/storio/sqlite/impl/auto_parcel/Book.java b/storio-sqlite/src/androidTest/java/com/pushtorefresh/storio/sqlite/impl/auto_parcel/Book.java
new file mode 100644
index 0000000..99b412d
--- /dev/null
+++ b/storio-sqlite/src/androidTest/java/com/pushtorefresh/storio/sqlite/impl/auto_parcel/Book.java
@@ -0,0 +1,38 @@
+package com.pushtorefresh.storio.sqlite.impl.auto_parcel;
+
+import android.support.annotation.NonNull;
+
+import auto.parcel.AutoParcel;
+
+@AutoParcel
+abstract class Book {
+
+    abstract int id();
+
+    @NonNull
+    abstract String title();
+
+    @NonNull
+    abstract String author();
+
+    @NonNull
+    static Builder builder() {
+        return new AutoParcel_Book.Builder();
+    }
+
+    @AutoParcel.Builder
+    abstract static class Builder {
+
+        @NonNull
+        abstract Builder id(int id);
+
+        @NonNull
+        abstract Builder title(@NonNull String title);
+
+        @NonNull
+        abstract Builder author(@NonNull String author);
+
+        @NonNull
+        abstract Book build();
+    }
+}
diff --git a/storio-sqlite/src/androidTest/java/com/pushtorefresh/storio/sqlite/impl/auto_parcel/BookTableMeta.java b/storio-sqlite/src/androidTest/java/com/pushtorefresh/storio/sqlite/impl/auto_parcel/BookTableMeta.java
new file mode 100644
index 0000000..e00cb5a
--- /dev/null
+++ b/storio-sqlite/src/androidTest/java/com/pushtorefresh/storio/sqlite/impl/auto_parcel/BookTableMeta.java
@@ -0,0 +1,99 @@
+package com.pushtorefresh.storio.sqlite.impl.auto_parcel;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.support.annotation.NonNull;
+
+import com.pushtorefresh.storio.sqlite.operation.delete.DefaultDeleteResolver;
+import com.pushtorefresh.storio.sqlite.operation.delete.DeleteResolver;
+import com.pushtorefresh.storio.sqlite.operation.get.DefaultGetResolver;
+import com.pushtorefresh.storio.sqlite.operation.get.GetResolver;
+import com.pushtorefresh.storio.sqlite.operation.put.DefaultPutResolver;
+import com.pushtorefresh.storio.sqlite.operation.put.PutResolver;
+import com.pushtorefresh.storio.sqlite.query.DeleteQuery;
+import com.pushtorefresh.storio.sqlite.query.InsertQuery;
+import com.pushtorefresh.storio.sqlite.query.UpdateQuery;
+
+final class BookTableMeta {
+
+    private BookTableMeta() {
+        throw new IllegalStateException("No instances please.");
+    }
+
+    @NonNull
+    static final String TABLE = "books";
+
+    @NonNull
+    static final String COLUMN_ID = "_id";
+
+    @NonNull
+    static final String COLUMN_TITLE = "title";
+
+    @NonNull
+    static final String COLUMN_AUTHOR = "author";
+
+    @NonNull
+    static final String SQL_CREATE_TABLE = "CREATE TABLE " + TABLE + "(" +
+            COLUMN_ID + " INTEGER PRIMARY KEY, " +
+            COLUMN_TITLE + " TEXT NOT NULL," +
+            COLUMN_AUTHOR + " TEXT NOT NULL);";
+
+    @NonNull
+    static final PutResolver<Book> PUT_RESOLVER = new DefaultPutResolver<Book>() {
+        @NonNull
+        @Override
+        protected InsertQuery mapToInsertQuery(@NonNull Book object) {
+            return new InsertQuery.Builder()
+                    .table(TABLE)
+                    .build();
+        }
+
+        @NonNull
+        @Override
+        protected UpdateQuery mapToUpdateQuery(@NonNull Book book) {
+            return new UpdateQuery.Builder()
+                    .table(TABLE)
+                    .where(COLUMN_ID + " = ?")
+                    .whereArgs(book.id())
+                    .build();
+        }
+
+        @NonNull
+        @Override
+        protected ContentValues mapToContentValues(@NonNull Book book) {
+            final ContentValues contentValues = new ContentValues(3);
+
+            contentValues.put(COLUMN_ID, book.id());
+            contentValues.put(COLUMN_TITLE, book.title());
+            contentValues.put(COLUMN_AUTHOR, book.author());
+
+            return contentValues;
+        }
+    };
+
+    @NonNull
+    static final GetResolver<Book> GET_RESOLVER = new DefaultGetResolver<Book>() {
+        @NonNull
+        @Override
+        public Book mapFromCursor(@NonNull Cursor cursor) {
+            return Book.builder()
+                    .id(cursor.getInt(cursor.getColumnIndex(COLUMN_ID)))
+                    .title(cursor.getString(cursor.getColumnIndex(COLUMN_TITLE)))
+                    .author(cursor.getString(cursor.getColumnIndex(COLUMN_AUTHOR)))
+                    .build();
+        }
+    };
+
+    @NonNull
+    static final DeleteResolver<Book> DELETE_RESOLVER = new DefaultDeleteResolver<Book>() {
+        @NonNull
+        @Override
+        protected DeleteQuery mapToDeleteQuery(@NonNull Book book) {
+            return new DeleteQuery.Builder()
+                    .table(TABLE)
+                    .where(COLUMN_ID + " = ?")
+                    .whereArgs(book.id())
+                    .build();
+        }
+    };
+}
diff --git a/storio-sqlite/src/androidTest/java/com/pushtorefresh/storio/sqlite/impl/auto_parcel/OpenHelper.java b/storio-sqlite/src/androidTest/java/com/pushtorefresh/storio/sqlite/impl/auto_parcel/OpenHelper.java
new file mode 100644
index 0000000..ffb1523
--- /dev/null
+++ b/storio-sqlite/src/androidTest/java/com/pushtorefresh/storio/sqlite/impl/auto_parcel/OpenHelper.java
@@ -0,0 +1,23 @@
+package com.pushtorefresh.storio.sqlite.impl.auto_parcel;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.support.annotation.NonNull;
+
+class OpenHelper extends SQLiteOpenHelper {
+
+    OpenHelper(@NonNull Context context) {
+        super(context, "auto_parcel_db", null, 1);
+    }
+
+    @Override
+    public void onCreate(SQLiteDatabase db) {
+        db.execSQL(BookTableMeta.SQL_CREATE_TABLE);
+    }
+
+    @Override
+    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+
+    }
+}
diff --git a/storio-sqlite/src/main/java/com/pushtorefresh/storio/sqlite/impl/DefaultStorIOSQLite.java b/storio-sqlite/src/main/java/com/pushtorefresh/storio/sqlite/impl/DefaultStorIOSQLite.java
index 8858b21..1e4462c 100644
--- a/storio-sqlite/src/main/java/com/pushtorefresh/storio/sqlite/impl/DefaultStorIOSQLite.java
+++ b/storio-sqlite/src/main/java/com/pushtorefresh/storio/sqlite/impl/DefaultStorIOSQLite.java
@@ -18,17 +18,18 @@
 import com.pushtorefresh.storio.sqlite.query.UpdateQuery;
 
 import java.io.IOException;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
 import rx.Observable;
 
 import static com.pushtorefresh.storio.internal.Checks.checkNotNull;
 import static com.pushtorefresh.storio.internal.Queries.nullableArrayOfStrings;
 import static com.pushtorefresh.storio.internal.Queries.nullableString;
+import static java.util.Collections.unmodifiableMap;
 
 /**
  * Default implementation of {@link StorIOSQLite} for {@link android.database.sqlite.SQLiteDatabase}.
@@ -165,8 +166,13 @@ public DefaultStorIOSQLite build() {
         @NonNull
         private final Object lock = new Object();
 
+        // Unmodifiable
         @Nullable
-        private final Map<Class<?>, SQLiteTypeMapping<?>> typesMapping;
+        private final Map<Class<?>, SQLiteTypeMapping<?>> directTypesMapping;
+
+        @NonNull
+        private final Map<Class<?>, SQLiteTypeMapping<?>> indirectTypesMappingCache
+                = new ConcurrentHashMap<Class<?>, SQLiteTypeMapping<?>>();
 
         /**
          * Guarded by {@link #lock}.
@@ -180,21 +186,77 @@ public DefaultStorIOSQLite build() {
         private final Set<Changes> pendingChanges = new HashSet<Changes>();
 
         protected InternalImpl(@Nullable Map<Class<?>, SQLiteTypeMapping<?>> typesMapping) {
-            this.typesMapping = typesMapping != null
-                    ? Collections.unmodifiableMap(typesMapping)
+            this.directTypesMapping = typesMapping != null
+                    ? unmodifiableMap(typesMapping)
                     : null;
         }
 
         /**
-         * {@inheritDoc}
+         * Gets type mapping for required type.
+         * <p/>
+         * This implementation can handle subclasses of types, that registered its type mapping.
+         * For example: You've added type mapping for {@code User.class},
+         * and you have {@code UserFromServiceA.class} which extends {@code User.class},
+         * and you didn't add type mapping for {@code UserFromServiceA.class}
+         * because they have same fields and you just want to have multiple classes.
+         * This implementation will find type mapping of {@code User.class}
+         * and use it as type mapping for {@code UserFromServiceA.class}.
+         *
+         * @return direct or indirect type mapping for passed type, or {@code null}.
          */
         @SuppressWarnings("unchecked")
         @Nullable
         @Override
-        public <T> SQLiteTypeMapping<T> typeMapping(@NonNull Class<T> type) {
-            return typesMapping != null
-                    ? (SQLiteTypeMapping<T>) typesMapping.get(type)
-                    : null;
+        public <T> SQLiteTypeMapping<T> typeMapping(final @NonNull Class<T> type) {
+            if (directTypesMapping == null) {
+                return null;
+            }
+
+            final SQLiteTypeMapping<T> directTypeMapping = (SQLiteTypeMapping<T>) directTypesMapping.get(type);
+
+            if (directTypeMapping != null) {
+                // fffast! O(1)
+                return directTypeMapping;
+            } else {
+                // If no direct type mapping found — search for indirect type mapping
+
+                // May be value already in cache.
+                SQLiteTypeMapping<T> indirectTypeMapping
+                        = (SQLiteTypeMapping<T>) indirectTypesMappingCache.get(type);
+
+                if (indirectTypeMapping != null) {
+                    // fffast! O(1)
+                    return indirectTypeMapping;
+                }
+
+                // Okay, we don't have direct type mapping.
+                // And we don't have cache for indirect type mapping.
+                // Let's find indirect type mapping and cache it!
+                Class<?> parentType = type.getSuperclass();
+
+                // Search algorithm:
+                // Walk through all parent types of passed type.
+                // If parent type has direct mapping -> we found indirect type mapping!
+                // If current parent type == Object.class -> there is no indirect type mapping.
+                // Complexity:
+                // O(n) where n is number of parent types of passed type (pretty fast).
+
+                // Stop search if root parent is Object.class
+                while (parentType != Object.class) {
+                    indirectTypeMapping = (SQLiteTypeMapping<T>) directTypesMapping.get(parentType);
+
+                    if (indirectTypeMapping != null) {
+                        // Store this typeMapping as known to make resolving O(1) for the next time
+                        indirectTypesMappingCache.put(type, indirectTypeMapping);
+                        return indirectTypeMapping;
+                    }
+
+                    parentType = parentType.getSuperclass();
+                }
+
+                // No indirect type mapping found.
+                return null;
+            }
         }
 
         /**
diff --git a/storio-sqlite/src/test/java/com/pushtorefresh/storio/sqlite/impl/DefaultStorIOSQLiteTest.java b/storio-sqlite/src/test/java/com/pushtorefresh/storio/sqlite/impl/DefaultStorIOSQLiteTest.java
index 9dd4e3c..de438cd 100644
--- a/storio-sqlite/src/test/java/com/pushtorefresh/storio/sqlite/impl/DefaultStorIOSQLiteTest.java
+++ b/storio-sqlite/src/test/java/com/pushtorefresh/storio/sqlite/impl/DefaultStorIOSQLiteTest.java
@@ -12,7 +12,8 @@
 
 import java.io.IOException;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -23,8 +24,7 @@
     @Test(expected = NullPointerException.class)
     public void nullSQLiteOpenHelper() {
         new DefaultStorIOSQLite.Builder()
-                .sqliteOpenHelper(null)
-                .build();
+                .sqliteOpenHelper(null);
     }
 
     @SuppressWarnings({"ConstantConditions", "unchecked"})
@@ -36,8 +36,7 @@ public void addTypeMappingNullType() {
                         .putResolver(mock(PutResolver.class))
                         .getResolver(mock(GetResolver.class))
                         .deleteResolver(mock(DeleteResolver.class))
-                        .build())
-                .build();
+                        .build());
     }
 
     @SuppressWarnings({"unchecked", "ConstantConditions"})
@@ -45,18 +44,165 @@ public void addTypeMappingNullType() {
     public void addTypeMappingNullMapping() {
         new DefaultStorIOSQLite.Builder()
                 .sqliteOpenHelper(mock(SQLiteOpenHelper.class))
-                .addTypeMapping(Object.class, null)
+                .addTypeMapping(Object.class, null);
+    }
+
+    @Test
+    public void shouldReturnNullIfNoTypeMappingsRegistered() {
+        class TestItem {
+
+        }
+
+        final StorIOSQLite storIOSQLite = new DefaultStorIOSQLite.Builder()
+                .sqliteOpenHelper(mock(SQLiteOpenHelper.class))
+                .build();
+
+        assertNull(storIOSQLite.internal().typeMapping(TestItem.class));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void shouldReturnNullIfNotTypeMappingRegisteredForType() {
+        class TestItem {
+
+        }
+
+        class Entity {
+
+        }
+
+        final SQLiteTypeMapping<Entity> entityContentResolverTypeMapping = new SQLiteTypeMapping.Builder<Entity>()
+                .putResolver(mock(PutResolver.class))
+                .getResolver(mock(GetResolver.class))
+                .deleteResolver(mock(DeleteResolver.class))
+                .build();
+
+        final StorIOSQLite storIOSQLite = new DefaultStorIOSQLite.Builder()
+                .sqliteOpenHelper(mock(SQLiteOpenHelper.class))
+                .addTypeMapping(Entity.class, entityContentResolverTypeMapping)
+                .build();
+
+        assertSame(entityContentResolverTypeMapping, storIOSQLite.internal().typeMapping(Entity.class));
+
+        assertNull(storIOSQLite.internal().typeMapping(TestItem.class));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void directTypeMappingShouldWork() {
+        class TestItem {
+
+        }
+
+        final SQLiteTypeMapping<TestItem> typeMapping = new SQLiteTypeMapping.Builder<TestItem>()
+                .putResolver(mock(PutResolver.class))
+                .getResolver(mock(GetResolver.class))
+                .deleteResolver(mock(DeleteResolver.class))
+                .build();
+
+        final StorIOSQLite storIOSQLite = new DefaultStorIOSQLite.Builder()
+                .sqliteOpenHelper(mock(SQLiteOpenHelper.class))
+                .addTypeMapping(TestItem.class, typeMapping)
+                .build();
+
+        assertSame(typeMapping, storIOSQLite.internal().typeMapping(TestItem.class));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void indirectTypeMappingShouldWork() {
+        class TestItem {
+
+        }
+
+        final SQLiteTypeMapping<TestItem> typeMapping = new SQLiteTypeMapping.Builder<TestItem>()
+                .putResolver(mock(PutResolver.class))
+                .getResolver(mock(GetResolver.class))
+                .deleteResolver(mock(DeleteResolver.class))
+                .build();
+
+        final StorIOSQLite storIOSQLite = new DefaultStorIOSQLite.Builder()
+                .sqliteOpenHelper(mock(SQLiteOpenHelper.class))
+                .addTypeMapping(TestItem.class, typeMapping)
                 .build();
+
+        class TestItemSubclass extends TestItem {
+
+        }
+
+        // Direct type mapping should still work
+        assertSame(typeMapping, storIOSQLite.internal().typeMapping(TestItem.class));
+
+        // Indirect type mapping should give same type mapping as for parent class
+        assertSame(typeMapping, storIOSQLite.internal().typeMapping(TestItemSubclass.class));
     }
 
     @SuppressWarnings("unchecked")
     @Test
-    public void typeMapping() {
+    public void typeMappingShouldWorkInCaseOfMoreConcreteTypeMapping() {
         class TestItem {
 
         }
 
-        final SQLiteTypeMapping<TestItem> testItemTypeDefinition = new SQLiteTypeMapping.Builder<TestItem>()
+        final SQLiteTypeMapping<TestItem> typeMapping = new SQLiteTypeMapping.Builder<TestItem>()
+                .putResolver(mock(PutResolver.class))
+                .getResolver(mock(GetResolver.class))
+                .deleteResolver(mock(DeleteResolver.class))
+                .build();
+
+
+        class TestItemSubclass extends TestItem {
+
+        }
+
+        final SQLiteTypeMapping<TestItemSubclass> subclassTypeMapping = new SQLiteTypeMapping.Builder<TestItemSubclass>()
+                .putResolver(mock(PutResolver.class))
+                .getResolver(mock(GetResolver.class))
+                .deleteResolver(mock(DeleteResolver.class))
+                .build();
+
+
+        final StorIOSQLite storIOSQLite = new DefaultStorIOSQLite.Builder()
+                .sqliteOpenHelper(mock(SQLiteOpenHelper.class))
+                .addTypeMapping(TestItem.class, typeMapping)
+                .addTypeMapping(TestItemSubclass.class, subclassTypeMapping)
+                .build();
+
+        // Parent class should have its own type mapping
+        assertSame(typeMapping, storIOSQLite.internal().typeMapping(TestItem.class));
+
+        // Child class should have its own type mapping
+        assertSame(subclassTypeMapping, storIOSQLite.internal().typeMapping(TestItemSubclass.class));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void typeMappingShouldFindIndirectTypeMappingInCaseOfComplexInheritance() {
+        // Good test case — inheritance with AutoValue/AutoParcel
+
+        class Entity {
+
+        }
+
+        class AutoValue_Entity extends Entity {
+
+        }
+
+        class ConcreteEntity extends Entity {
+
+        }
+
+        class AutoValue_ConcreteEntity extends ConcreteEntity {
+
+        }
+
+        final SQLiteTypeMapping<Entity> entitySQLiteTypeMapping = new SQLiteTypeMapping.Builder<Entity>()
+                .putResolver(mock(PutResolver.class))
+                .getResolver(mock(GetResolver.class))
+                .deleteResolver(mock(DeleteResolver.class))
+                .build();
+
+        final SQLiteTypeMapping<ConcreteEntity> concreteEntitySQLiteTypeMapping = new SQLiteTypeMapping.Builder<ConcreteEntity>()
                 .putResolver(mock(PutResolver.class))
                 .getResolver(mock(GetResolver.class))
                 .deleteResolver(mock(DeleteResolver.class))
@@ -64,10 +210,21 @@ public void typeMapping() {
 
         final StorIOSQLite storIOSQLite = new DefaultStorIOSQLite.Builder()
                 .sqliteOpenHelper(mock(SQLiteOpenHelper.class))
-                .addTypeMapping(TestItem.class, testItemTypeDefinition)
+                .addTypeMapping(Entity.class, entitySQLiteTypeMapping)
+                .addTypeMapping(ConcreteEntity.class, concreteEntitySQLiteTypeMapping)
                 .build();
 
-        assertEquals(testItemTypeDefinition, storIOSQLite.internal().typeMapping(TestItem.class));
+        // Direct type mapping for Entity should work
+        assertSame(entitySQLiteTypeMapping, storIOSQLite.internal().typeMapping(Entity.class));
+
+        // Direct type mapping for ConcreteEntity should work
+        assertSame(concreteEntitySQLiteTypeMapping, storIOSQLite.internal().typeMapping(ConcreteEntity.class));
+
+        // Indirect type mapping for AutoValue_Entity should get type mapping for Entity
+        assertSame(entitySQLiteTypeMapping, storIOSQLite.internal().typeMapping(AutoValue_Entity.class));
+
+        // Indirect type mapping for AutoValue_ConcreteEntity should get type mapping for ConcreteEntity, not for Entity!
+        assertSame(concreteEntitySQLiteTypeMapping, storIOSQLite.internal().typeMapping(AutoValue_ConcreteEntity.class));
     }
 
     @Test
