Skip to content

distinct sql and ignore field in filters and sorting #95

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.introproventures.graphql.jpa.query.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target( { TYPE, FIELD })
@Retention(RUNTIME)
public @interface GraphQLIgnoreFilter {
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.introproventures.graphql.jpa.query.annotation;


import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target( { FIELD })
@Retention(RUNTIME)
public @interface GraphQLIgnoreOrder {
}

Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ public class GraphQLJpaQueryProperties {
@NotEmpty
private String description;

/**
* Enable or disable distinct parameter.
*/
private boolean useDistinctParameter;

/**
* Enable or disable distinct distinct sql query fetcher.
*/
private boolean distinctFetcher;

/**
* Enable or disable QraphQL module services.
*/
Expand Down Expand Up @@ -78,6 +88,34 @@ public void setDescription(String description) {
this.description = description;
}

/**
* @return the useDistinctParameter
*/
public boolean isUseDistinctParameter() {
return useDistinctParameter;
}

/**
* @param useDistinctParameter the useDistinctParameter to set
*/
public void setUseDistinctParameter(boolean useDistinctParameter) {
this.useDistinctParameter = useDistinctParameter;
}

/**
* @return the distinctFetcher
*/
public boolean isDistinctFetcher() {
return distinctFetcher;
}

/**
* @param distinctFetcher the distinctFetcher to set
*/
public void setDistinctFetcher(boolean distinctFetcher) {
this.distinctFetcher = distinctFetcher;
}

/**
* @return the enabled
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
spring.graphql.jpa.query.name=Query
spring.graphql.jpa.query.description=
spring.graphql.jpa.query.useDistinctParameter=false
spring.graphql.jpa.query.distinctFetcher=false
spring.graphql.jpa.query.enabled=true
spring.graphql.jpa.query.path=/graphql
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
spring.graphql.jpa.query.name=GraphQLJpaQuery
spring.graphql.jpa.query.description=GraphQL Jpa Query Schema Specification
spring.graphql.jpa.query.useDistinctParameter=false
spring.graphql.jpa.query.distinctFetcher=false
spring.graphql.jpa.query.enabled=true
spring.graphql.jpa.query.path=/graphql
2 changes: 1 addition & 1 deletion graphql-jpa-query-example-merge/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<groupId>com.introproventures</groupId>
<artifactId>graphql-jpa-query-autoconfigure</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import com.introproventures.graphql.jpa.query.annotation.GraphQLIgnoreFilter;
import com.introproventures.graphql.jpa.query.annotation.GraphQLIgnoreOrder;
import lombok.Data;

@Data
Expand All @@ -31,6 +33,8 @@ public class Book {
@Id
Long id;

@GraphQLIgnoreOrder
@GraphQLIgnoreFilter
String title;

@ManyToOne(fetch=FetchType.LAZY)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import com.introproventures.graphql.jpa.query.autoconfigure.GraphQLJpaQueryProperties;
import com.introproventures.graphql.jpa.query.autoconfigure.GraphQLSchemaConfigurer;
import com.introproventures.graphql.jpa.query.autoconfigure.GraphQLShemaRegistration;
import com.introproventures.graphql.jpa.query.schema.impl.GraphQLJpaSchemaBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.H2Dialect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
Expand Down Expand Up @@ -74,14 +76,22 @@ public static class GraphQLJpaQuerySchemaConfigurer implements GraphQLSchemaConf

private final EntityManager entityManager;

@Autowired
private GraphQLJpaQueryProperties properties;

public GraphQLJpaQuerySchemaConfigurer(@Qualifier("bookEntityManager") EntityManagerFactory entityManager) {
this.entityManager = entityManager.createEntityManager();
}

@Override
public void configure(GraphQLShemaRegistration registry) {

registry.register(new GraphQLJpaSchemaBuilder(entityManager).name("GraphQLBooks").build());
registry.register(
new GraphQLJpaSchemaBuilder(entityManager)
.name("GraphQLBooks")
.useDistinctParameter(properties.isUseDistinctParameter())
.setDistinctFetcher(properties.isDistinctFetcher())
.build()
);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ spring:
query:
name: Query
description: Combined GraphQL Jpa Query for Starwars and Books Example
useDistinctParameter: true
enabled: true
path: graphql

starwars:
hikari:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
*
*/
class GraphQLJpaQueryDataFetcher extends QraphQLJpaBaseDataFetcher {

private boolean defaultDistinct = false;

private static final String HIBERNATE_QUERY_PASS_DISTINCT_THROUGH = "hibernate.query.passDistinctThrough";
private static final String ORG_HIBERNATE_CACHEABLE = "org.hibernate.cacheable";
Expand All @@ -57,6 +59,19 @@ public GraphQLJpaQueryDataFetcher(EntityManager entityManager, EntityType<?> ent
super(entityManager, entityType);
}

public GraphQLJpaQueryDataFetcher(EntityManager entityManager, EntityType<?> entityType, boolean defaultDistinct) {
super(entityManager, entityType);
this.defaultDistinct = defaultDistinct;
}

public boolean isDefaultDistinct() {
return defaultDistinct;
}

public void setDefaultDistinct(boolean defaultDistinct) {
this.defaultDistinct = defaultDistinct;
}

@Override
public Object get(DataFetchingEnvironment environment) {
Field field = environment.getFields().iterator().next();
Expand All @@ -69,7 +84,7 @@ public Object get(DataFetchingEnvironment environment) {

Optional<Argument> pageArgument = getPageArgument(field);
Page page = extractPageArgument(environment, field);
Argument distinctArg = extractArgument(environment, field, GraphQLJpaSchemaBuilder.SELECT_DISTINCT_PARAM_NAME, new BooleanValue(true));
Argument distinctArg = extractArgument(environment, field, GraphQLJpaSchemaBuilder.SELECT_DISTINCT_PARAM_NAME, new BooleanValue(defaultDistinct));

boolean isDistinct = ((BooleanValue) distinctArg.getValue()).isValue();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.Type;

import com.introproventures.graphql.jpa.query.annotation.GraphQLIgnoreFilter;
import com.introproventures.graphql.jpa.query.annotation.GraphQLIgnoreOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -113,6 +115,9 @@ public class GraphQLJpaSchemaBuilder implements GraphQLSchemaBuilder {

private String description = "GraphQL Schema for all entities in this JPA application";

private boolean distinctParameter = false;
private boolean distinctFetcher = false;

public GraphQLJpaSchemaBuilder(EntityManager entityManager) {
this.entityManager = entityManager;
}
Expand Down Expand Up @@ -192,22 +197,34 @@ private GraphQLFieldDefinition getQueryFieldSelectDefinition(EntityType<?> entit
.build()
)
.build();
return GraphQLFieldDefinition.newFieldDefinition()

GraphQLFieldDefinition.Builder fdBuilder = GraphQLFieldDefinition.newFieldDefinition()
.name(namingStrategy.pluralize(entityType.getName()))
.description("Query request wrapper for " + entityType.getName() + " to request paginated data. "
+ "Use query request arguments to specify query filter criterias. "
+ "Use the '"+QUERY_SELECT_PARAM_NAME+"' field to request actual fields. "
+ "Use the '"+ORDER_BY_PARAM_NAME+"' on a field to specify sort order for each field. ")
.type(pageType)
.dataFetcher(new GraphQLJpaQueryDataFetcher(entityManager, entityType))
.dataFetcher(new GraphQLJpaQueryDataFetcher(entityManager, entityType, distinctFetcher))
.argument(paginationArgument)
.argument(getWhereArgument(entityType))
.build();
.argument(getWhereArgument(entityType));
if (distinctParameter) {
fdBuilder.argument(distinctArgument(entityType));
}

return fdBuilder.build();
}

private Map<Class<?>, GraphQLArgument> whereArgumentsMap = new HashMap<>();

private GraphQLArgument distinctArgument(EntityType<?> entityType) {
return GraphQLArgument.newArgument()
.name(SELECT_DISTINCT_PARAM_NAME)
.description("Distinct logical specification")
.type(Scalars.GraphQLBoolean)
.build();
}

private GraphQLArgument getWhereArgument(ManagedType<?> managedType) {
String typeName="";
if (managedType instanceof EmbeddableType){
Expand Down Expand Up @@ -241,18 +258,21 @@ private GraphQLArgument getWhereArgument(ManagedType<?> managedType) {
.fields(managedType.getAttributes().stream()
.filter(this::isValidInput)
.filter(this::isNotIgnored)
.filter(this::isNotIgnoredFilter)
.map(this::getWhereInputField)
.collect(Collectors.toList())
)
.fields(managedType.getAttributes().stream()
.filter(this::isToOne)
.filter(this::isNotIgnored)
.filter(this::isNotIgnoredFilter)
.map(this::getInputObjectField)
.collect(Collectors.toList())
)
.fields(managedType.getAttributes().stream()
.filter(this::isToMany)
.filter(this::isNotIgnored)
.filter(this::isNotIgnoredFilter)
.map(this::getInputObjectField)
.collect(Collectors.toList())
)
Expand Down Expand Up @@ -302,6 +322,7 @@ private GraphQLInputObjectType computeWhereInputType(ManagedType<?> managedType)
.fields(managedType.getAttributes().stream()
.filter(this::isValidInput)
.filter(this::isNotIgnored)
.filter(this::isNotIgnoredFilter)
.map(this::getWhereInputField)
.collect(Collectors.toList())
)
Expand Down Expand Up @@ -568,7 +589,8 @@ private GraphQLFieldDefinition getObjectField(Attribute attribute) {

// Only add the orderBy argument for basic attribute types
if (attribute instanceof SingularAttribute
&& attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.BASIC) {
&& attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.BASIC
&& isNotIgnoredOrder(attribute) ) {
arguments.add(GraphQLArgument.newArgument()
.name(ORDER_BY_PARAM_NAME)
.description("Specifies field sort direction in the query results.")
Expand Down Expand Up @@ -816,6 +838,37 @@ private boolean isNotIgnored(AnnotatedElement annotatedElement) {

return false;
}

protected boolean isNotIgnoredFilter(Attribute<?,?> attribute) {
return isNotIgnoredFilter(attribute.getJavaMember()) && isNotIgnoredFilter(attribute.getJavaType());
}

protected boolean isNotIgnoredFilter(EntityType<?> entityType) {
return isNotIgnoredFilter(entityType.getJavaType());
}

protected boolean isNotIgnoredFilter(Member member) {
return member instanceof AnnotatedElement && isNotIgnoredFilter((AnnotatedElement) member);
}

protected boolean isNotIgnoredFilter(AnnotatedElement annotatedElement) {
if (annotatedElement != null) {
GraphQLIgnoreFilter schemaDocumentation = annotatedElement.getAnnotation(GraphQLIgnoreFilter.class);
return schemaDocumentation == null;
}

return false;
}

protected boolean isNotIgnoredOrder(Attribute<?,?> attribute) {
AnnotatedElement annotatedElement = (AnnotatedElement)attribute.getJavaMember();
if (annotatedElement != null) {
GraphQLIgnoreOrder schemaDocumentation = annotatedElement.getAnnotation(GraphQLIgnoreOrder.class);
return schemaDocumentation == null;
}
return false;
}


@SuppressWarnings( "unchecked" )
private GraphQLOutputType getGraphQLTypeFromJavaType(Class<?> clazz) {
Expand Down Expand Up @@ -934,6 +987,26 @@ public GraphQLJpaSchemaBuilder description(String description) {
return this;
}

public GraphQLJpaSchemaBuilder useDistinctParameter(boolean distinctArgument) {
this.distinctParameter = distinctArgument;

return this;
}

public boolean isDistinctParameter() {
return distinctParameter;
}

public boolean isDistinctFetcher() {
return distinctFetcher;
}

public GraphQLJpaSchemaBuilder setDistinctFetcher(boolean distinctFetcher) {
this.distinctFetcher = distinctFetcher;

return this;
}

/**
* @param namingStrategy the namingStrategy to set
*/
Expand Down
Loading