diff --git a/graphql-jpa-query-annotations/src/main/java/com/introproventures/graphql/jpa/query/annotation/GraphQLReadEntityForRole.java b/graphql-jpa-query-annotations/src/main/java/com/introproventures/graphql/jpa/query/annotation/GraphQLReadEntityForRole.java
new file mode 100644
index 000000000..f3e577502
--- /dev/null
+++ b/graphql-jpa-query-annotations/src/main/java/com/introproventures/graphql/jpa/query/annotation/GraphQLReadEntityForRole.java
@@ -0,0 +1,13 @@
+package com.introproventures.graphql.jpa.query.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface GraphQLReadEntityForRole {
+    String[] value();
+}
diff --git a/graphql-jpa-query-example-model-books/src/main/java/com/introproventures/graphql/jpa/query/schema/model/book/Author.java b/graphql-jpa-query-example-model-books/src/main/java/com/introproventures/graphql/jpa/query/schema/model/book/Author.java
index 406c81b6e..e4b91886c 100644
--- a/graphql-jpa-query-example-model-books/src/main/java/com/introproventures/graphql/jpa/query/schema/model/book/Author.java
+++ b/graphql-jpa-query-example-model-books/src/main/java/com/introproventures/graphql/jpa/query/schema/model/book/Author.java
@@ -31,6 +31,7 @@
 import javax.persistence.OneToMany;
 import javax.persistence.OrderBy;
 
+import com.introproventures.graphql.jpa.query.annotation.GraphQLReadEntityForRole;
 import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.Setter;
@@ -41,6 +42,7 @@
 @Setter
 @ToString
 @EqualsAndHashCode(exclude={"books","phoneNumbers"}) // Fixes NPE in Hibernate when initializing loaded collections #1
+@GraphQLReadEntityForRole({"admin"})
 public class Author {
 	@Id
 	Long id;
diff --git a/graphql-jpa-query-example-model-books/src/main/java/com/introproventures/graphql/jpa/query/schema/model/book/Book.java b/graphql-jpa-query-example-model-books/src/main/java/com/introproventures/graphql/jpa/query/schema/model/book/Book.java
index ce8045270..2fe40307d 100644
--- a/graphql-jpa-query-example-model-books/src/main/java/com/introproventures/graphql/jpa/query/schema/model/book/Book.java
+++ b/graphql-jpa-query-example-model-books/src/main/java/com/introproventures/graphql/jpa/query/schema/model/book/Book.java
@@ -29,10 +29,7 @@
 import javax.persistence.ManyToOne;
 import javax.persistence.Transient;
 
-import com.introproventures.graphql.jpa.query.annotation.GraphQLDescription;
-import com.introproventures.graphql.jpa.query.annotation.GraphQLIgnore;
-import com.introproventures.graphql.jpa.query.annotation.GraphQLIgnoreFilter;
-import com.introproventures.graphql.jpa.query.annotation.GraphQLIgnoreOrder;
+import com.introproventures.graphql.jpa.query.annotation.*;
 
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -40,6 +37,7 @@
 @Data
 @Entity
 @EqualsAndHashCode(exclude= {"author", "tags"})
+@GraphQLReadEntityForRole({"user", "admin"})
 public class Book {
 	@Id
 	Long id;
diff --git a/graphql-jpa-query-schema-mutations/pom.xml b/graphql-jpa-query-schema-mutations/pom.xml
new file mode 100644
index 000000000..2cfdb74f0
--- /dev/null
+++ b/graphql-jpa-query-schema-mutations/pom.xml
@@ -0,0 +1,76 @@
+
+
+    
+        com.introproventures
+        graphql-jpa-query-build
+        0.3.36-SNAPSHOT
+        ../graphql-jpa-query-build
+    
+    4.0.0
+
+    graphql-jpa-query-schema-mutations
+    graphql-jpa-query-schema-mutations
+
+    
+        
+            com.introproventures
+            graphql-jpa-query-annotations
+        
+
+        
+            com.introproventures
+            graphql-jpa-query-schema
+        
+
+        
+            javax.persistence
+            javax.persistence-api
+        
+
+        
+            javax.transaction
+            javax.transaction-api
+        
+
+        
+            javax.interceptor
+            javax.interceptor-api
+        
+
+        
+            org.slf4j
+            slf4j-api
+        
+
+        
+        
+            com.fasterxml.jackson.datatype
+            jackson-datatype-jsr310
+            2.9.8
+        
+
+        
+        
+            org.json
+            json
+            20180813
+        
+
+        
+        
+            org.apache.commons
+            commons-lang3
+            3.8.1
+        
+
+        
+            org.springframework.boot
+            spring-boot-starter-data-jpa
+            test
+        
+
+    
+
+
\ No newline at end of file
diff --git a/graphql-jpa-query-schema-mutations/src/main/java/com/introproventures/graphql/jpa/query/mutations/GraphQLJpaSchemaBuilderWithMutation.java b/graphql-jpa-query-schema-mutations/src/main/java/com/introproventures/graphql/jpa/query/mutations/GraphQLJpaSchemaBuilderWithMutation.java
new file mode 100644
index 000000000..058e45d98
--- /dev/null
+++ b/graphql-jpa-query-schema-mutations/src/main/java/com/introproventures/graphql/jpa/query/mutations/GraphQLJpaSchemaBuilderWithMutation.java
@@ -0,0 +1,206 @@
+package com.introproventures.graphql.jpa.query.mutations;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import com.introproventures.graphql.jpa.query.mutations.fetcher.impl.*;
+
+import javax.persistence.EntityManager;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.EmbeddableType;
+import javax.persistence.metamodel.EntityType;
+import javax.persistence.metamodel.PluralAttribute;
+import javax.persistence.metamodel.SingularAttribute;
+import javax.persistence.metamodel.Type;
+
+import com.introproventures.graphql.jpa.query.schema.impl.FetcherParams;
+import com.introproventures.graphql.jpa.query.schema.impl.GraphQLJpaSchemaBuilder;
+
+import graphql.schema.*;
+
+
+public class GraphQLJpaSchemaBuilderWithMutation extends GraphQLJpaSchemaBuilder {
+	public class GqlMutationOper {
+		private String operation;
+		private String description;
+		private Class extends GraphQLJpaEntityInputFetcher> fetcher;
+		
+		public GqlMutationOper(String oper, String description, Class extends GraphQLJpaEntityInputFetcher> fetcher) {
+			this.operation = oper;
+			this.description = description;
+			this.fetcher = fetcher;
+		}
+
+		public String getOperation() {
+			return operation;
+		}
+
+		public void setOperation(String operation) {
+			this.operation = operation;
+		}
+
+		public String getDescription() {
+			return description;
+		}
+
+		public void setDescription(String description) {
+			this.description = description;
+		}
+
+		public Class extends GraphQLJpaEntityInputFetcher> getFetcher() {
+			return fetcher;
+		}
+
+		public void setFetcher(Class extends GraphQLJpaEntityInputFetcher> fetcher) {
+			this.fetcher = fetcher;
+		}		
+	}
+
+	protected String suffixInputObjectType = "Input";
+	private List operations = new ArrayList<>(); 
+	private Map, GraphQLInputObjectType> entityInputCache = new HashMap<>();
+
+	public GraphQLJpaSchemaBuilderWithMutation(EntityManager em) {
+		super(em);
+
+		operations.add(new GqlMutationOper("insert", "This insert entity", InsertFecher.class));
+		operations.add(new GqlMutationOper("update", "This update entity", UpdateFetcher.class));
+		operations.add(new GqlMutationOper("merge", "This update entity", MergeFetcher.class));
+		operations.add(new GqlMutationOper("delete", "This delete entity", DeleteFetcher.class));
+	}
+
+	public GraphQLJpaSchemaBuilderWithMutation suffixInputObjectType(String suffixInputObjectType) {
+		this.suffixInputObjectType = suffixInputObjectType;
+		return this;
+	}
+
+	@Override
+	public GraphQLSchema build() {
+		createFetcherParams();
+		return GraphQLSchema.newSchema()
+				.query(getQueryType())
+	            .mutation(getMutation())
+	            .build();
+	}
+	
+	protected GraphQLObjectType getMutation() {
+		GraphQLObjectType.Builder queryType = 
+	        GraphQLObjectType.newObject()
+	                .name("editEntities")
+	                .description(this.getDescription());
+		
+		List fields = new ArrayList<>();
+
+		for (EntityType> entityType : entityManager.getMetamodel().getEntities()) {
+			if (!isNotIgnored(entityType)) continue;
+
+			for (GqlMutationOper oper : operations) {				
+				fields.add(getMutationDefinition(entityType, oper));
+			}
+		}
+	        
+	    queryType.fields(fields);	        			            
+	    return queryType.build();
+	}
+	
+	private GraphQLFieldDefinition getMutationDefinition(EntityType> entityType, GqlMutationOper oper) {		
+        return GraphQLFieldDefinition.newFieldDefinition()
+                .name(oper.getOperation()+entityType.getName())
+                .description(oper.getDescription())
+                .type(getObjectType(entityType))
+                .dataFetcher(getInputFetcher(entityType, oper))
+                .argument(getArgumentInputEntity(entityType))                
+                .build();
+    } 
+	
+	private GraphQLJpaEntityInputFetcher getInputFetcher(EntityType> entityType, GqlMutationOper oper) {
+		Class extends GraphQLJpaEntityInputFetcher> classFetch  = oper.getFetcher();
+		try {
+			return classFetch.getDeclaredConstructor(EntityManager.class, FetcherParams.class, EntityType.class)
+					.newInstance(entityManager, fetcherParams, entityType);
+		} catch(Exception e) {
+			throw new RuntimeException(e);
+		}		
+	}
+
+	
+	private GraphQLArgument getArgumentInputEntity(EntityType> entityType) {
+		return GraphQLArgument.newArgument()
+	        .name("entity")
+	        .type(getObjectInputType(entityType))
+	        .description("this description entity " + entityType.getName())
+	        .build();
+	}
+	
+    private GraphQLInputObjectType getObjectInputType(EntityType> entityType) {
+        if (entityInputCache.containsKey(entityType))
+            return entityInputCache.get(entityType);        
+        
+        GraphQLInputObjectType objectInputType = GraphQLInputObjectType.newInputObject()
+                .name(entityType.getName()+suffixInputObjectType)
+                .description("Input type GraphQL for entity "+entityType.getName())
+                
+                .fields(entityType.getAttributes().stream()
+                    .filter(this::isNotIgnored)
+                    .map(this::getObjectInputAttribute)
+                    .collect(Collectors.toList())
+                )
+                .build();
+        
+        entityInputCache.putIfAbsent(entityType, objectInputType);
+        
+        return objectInputType;
+    }
+    
+    public GraphQLInputObjectField getObjectInputAttribute(Attribute,?> attribute) {   
+    	GraphQLType type = getAttributeInputType(attribute);
+    	
+    	if (!(type instanceof GraphQLInputType)) {
+    		throw new IllegalArgumentException("Attribute " + attribute + " cannot be instanceof GraphQLInputType");
+    	}
+    	
+    	GraphQLInputObjectField field = GraphQLInputObjectField.newInputObjectField()
+    			.name(attribute.getName())
+    			.type((GraphQLInputType)type)    			
+    			.build();
+    	
+    	return field;
+    }
+
+    @SuppressWarnings( "rawtypes" )
+	protected GraphQLType getAttributeInputType(Attribute,?> attribute) {
+    	
+        if (isBasic(attribute)) {
+        	return getGraphQLTypeFromJavaType(attribute.getJavaType());        	
+        } 
+        else if (isEmbeddable(attribute)) {
+        	EmbeddableType embeddableType = (EmbeddableType) ((SingularAttribute) attribute).getType();
+        	return getEmbeddableType(embeddableType, true );
+        } 
+        else if (isToMany(attribute)) {
+            EntityType foreignType = (EntityType) ((PluralAttribute) attribute).getElementType();
+            return new GraphQLList(new GraphQLTypeReference(foreignType.getName()+suffixInputObjectType));
+        } 
+        else if (isToOne(attribute)) {
+            EntityType foreignType = (EntityType) ((SingularAttribute) attribute).getType();
+            return new GraphQLTypeReference(foreignType.getName()+suffixInputObjectType);
+        } 
+        else if (isElementCollection(attribute)) {
+            Type foreignType = ((PluralAttribute) attribute).getElementType();
+            
+            if(foreignType.getPersistenceType() == Type.PersistenceType.BASIC) {
+            	return new GraphQLList(getGraphQLTypeFromJavaType(foreignType.getJavaType()));        	
+            }
+        }
+
+        final String declaringType = attribute.getDeclaringType().getJavaType().getName(); // fully qualified name of the entity class
+        final String declaringMember = attribute.getJavaMember().getName(); // field name in the entity class
+
+        throw new UnsupportedOperationException(
+                "Attribute could not be mapped to GraphQL: field '" + declaringMember + "' of entity class '"+ declaringType +"'");
+    }
+}
diff --git a/graphql-jpa-query-schema-mutations/src/main/java/com/introproventures/graphql/jpa/query/mutations/annotation/GraphQLWriteEntityForRole.java b/graphql-jpa-query-schema-mutations/src/main/java/com/introproventures/graphql/jpa/query/mutations/annotation/GraphQLWriteEntityForRole.java
new file mode 100644
index 000000000..d6ec0318d
--- /dev/null
+++ b/graphql-jpa-query-schema-mutations/src/main/java/com/introproventures/graphql/jpa/query/mutations/annotation/GraphQLWriteEntityForRole.java
@@ -0,0 +1,17 @@
+package com.introproventures.graphql.jpa.query.mutations.annotation;
+
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface GraphQLWriteEntityForRole {
+    String[] value();
+
+    GraphQLWriteType[] operations() default {GraphQLWriteType.ALL};
+}
+
+
diff --git a/graphql-jpa-query-schema-mutations/src/main/java/com/introproventures/graphql/jpa/query/mutations/annotation/GraphQLWriteEntityList.java b/graphql-jpa-query-schema-mutations/src/main/java/com/introproventures/graphql/jpa/query/mutations/annotation/GraphQLWriteEntityList.java
new file mode 100644
index 000000000..6c4eeae44
--- /dev/null
+++ b/graphql-jpa-query-schema-mutations/src/main/java/com/introproventures/graphql/jpa/query/mutations/annotation/GraphQLWriteEntityList.java
@@ -0,0 +1,17 @@
+package com.introproventures.graphql.jpa.query.mutations.annotation;
+
+import com.introproventures.graphql.jpa.query.mutations.annotation.GraphQLWriteEntityForRole;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface GraphQLWriteEntityList {
+    GraphQLWriteEntityForRole[] value();
+}
+
+
+
diff --git a/graphql-jpa-query-schema-mutations/src/main/java/com/introproventures/graphql/jpa/query/mutations/annotation/GraphQLWriteType.java b/graphql-jpa-query-schema-mutations/src/main/java/com/introproventures/graphql/jpa/query/mutations/annotation/GraphQLWriteType.java
new file mode 100644
index 000000000..374acd797
--- /dev/null
+++ b/graphql-jpa-query-schema-mutations/src/main/java/com/introproventures/graphql/jpa/query/mutations/annotation/GraphQLWriteType.java
@@ -0,0 +1,8 @@
+package com.introproventures.graphql.jpa.query.mutations.annotation;
+
+public enum GraphQLWriteType {
+    ALL,
+    INSERT,
+    UPDATE,
+    DELETE
+}
diff --git a/graphql-jpa-query-schema-mutations/src/main/java/com/introproventures/graphql/jpa/query/mutations/fetcher/IGraphQLJpaEntityInputFetcher.java b/graphql-jpa-query-schema-mutations/src/main/java/com/introproventures/graphql/jpa/query/mutations/fetcher/IGraphQLJpaEntityInputFetcher.java
new file mode 100644
index 000000000..9f2b9c66c
--- /dev/null
+++ b/graphql-jpa-query-schema-mutations/src/main/java/com/introproventures/graphql/jpa/query/mutations/fetcher/IGraphQLJpaEntityInputFetcher.java
@@ -0,0 +1,7 @@
+package com.introproventures.graphql.jpa.query.mutations.fetcher;
+
+import graphql.schema.DataFetcher;
+
+public interface IGraphQLJpaEntityInputFetcher extends DataFetcher