@Override public <T, M> CompositeObject migrate( T instance, MigrationStrategy<T, M> migrationStrategy, Class<M> targetType, Class<?>... targetTypes) { AbstractInstanceManager<EntityId, Entity> entityInstanceManager = sessionContext.getEntityInstanceManager(); Entity entity = entityInstanceManager.getDatastoreType(instance); DatastoreSession< EntityId, Entity, EntityMetadata, EntityDiscriminator, RelationId, Relation, RelationMetadata, RelationDiscriminator, PropertyMetadata> datastoreSession = sessionContext.getDatastoreSession(); Set<EntityDiscriminator> entityDiscriminators = datastoreSession.getDatastoreEntityManager().getEntityDiscriminators(entity); MetadataProvider<EntityMetadata, EntityDiscriminator, RelationMetadata, RelationDiscriminator> metadataProvider = sessionContext.getMetadataProvider(); TypeMetadataSet<EntityTypeMetadata<EntityMetadata>> types = metadataProvider.getTypes(entityDiscriminators); TypeMetadataSet<EntityTypeMetadata<EntityMetadata>> effectiveTargetTypes = getEffectiveTypes(targetType, targetTypes); Set<EntityDiscriminator> targetEntityDiscriminators = metadataProvider.getEntityDiscriminators(effectiveTargetTypes); datastoreSession .getDatastoreEntityManager() .migrateEntity( entity, types, entityDiscriminators, effectiveTargetTypes, targetEntityDiscriminators); entityInstanceManager.removeInstance(instance); CompositeObject migratedInstance = entityInstanceManager.updateInstance(entity); if (migrationStrategy != null) { migrationStrategy.migrate(instance, migratedInstance.as(targetType)); } entityInstanceManager.closeInstance(instance); return migratedInstance; }