From ddfb4bc152a447eb2403a05ae2c3b4d6a0ae6319 Mon Sep 17 00:00:00 2001 From: remmeier Date: Sat, 24 Sep 2016 21:38:40 +0200 Subject: [PATCH] #15 JPAModule many-relation fix fixed querydsl integration and added test cases --- .../RelationshipRepositoryAdapter.java | 8 +- .../ResourceRepositoryAdapter.java | 6 +- .../ResponseRepository.java | 5 +- .../jpa/JpaRelationshipRepository.java | 3 +- .../jpa/internal/query/JoinRegistry.java | 7 +- .../query/backend/JpaQueryBackend.java | 2 +- .../criteria/JpaCriteriaQueryBackend.java | 2 +- .../querydsl/QuerydslQueryBackend.java | 104 ++++++++++++------ .../query/backend/querydsl/QuerydslUtils.java | 33 +++--- .../katharsis/jpa/AbstractJpaJerseyTest.java | 2 + .../jpa/JpaQuerySpecEndToEndTest.java | 74 ++++++++++++- .../JpaRelationshipRepositoryTestBase.java | 7 -- 12 files changed, 183 insertions(+), 70 deletions(-) diff --git a/katharsis-core/src/main/java/io/katharsis/resource/registry/responseRepository/RelationshipRepositoryAdapter.java b/katharsis-core/src/main/java/io/katharsis/resource/registry/responseRepository/RelationshipRepositoryAdapter.java index a55ae5f2..5fc3a96a 100644 --- a/katharsis-core/src/main/java/io/katharsis/resource/registry/responseRepository/RelationshipRepositoryAdapter.java +++ b/katharsis-core/src/main/java/io/katharsis/resource/registry/responseRepository/RelationshipRepositoryAdapter.java @@ -82,7 +82,9 @@ public JsonApiResponse findOneTarget(T_ID sourceId, String fieldName, QueryAdapt resource = ((AnnotatedRelationshipRepositoryAdapter) relationshipRepository) .findOneTarget(sourceId, fieldName, toQueryParams(queryAdapter)); } else if(relationshipRepository instanceof QuerySpecRelationshipRepository){ - resource = ((QuerySpecRelationshipRepository)relationshipRepository).findOneTarget(sourceId, fieldName, toQuerySpec(queryAdapter)); + QuerySpecRelationshipRepository querySpecRepository = (QuerySpecRelationshipRepository) relationshipRepository; + Class targetResourceClass = querySpecRepository.getTargetResourceClass(); + resource = querySpecRepository.findOneTarget(sourceId, fieldName, toQuerySpec(queryAdapter, targetResourceClass)); } else { resource = ((RelationshipRepository) relationshipRepository) .findOneTarget(sourceId, fieldName, toQueryParams(queryAdapter)); @@ -96,7 +98,9 @@ public JsonApiResponse findManyTargets(T_ID sourceId, String fieldName, QueryAda resources = ((AnnotatedRelationshipRepositoryAdapter) relationshipRepository) .findManyTargets(sourceId, fieldName, toQueryParams(queryAdapter)); }else if(relationshipRepository instanceof QuerySpecRelationshipRepository){ - resources = ((QuerySpecRelationshipRepository)relationshipRepository).findManyTargets(sourceId, fieldName, toQuerySpec(queryAdapter)); + QuerySpecRelationshipRepository querySpecRepository = (QuerySpecRelationshipRepository) relationshipRepository; + Class targetResourceClass = querySpecRepository.getTargetResourceClass(); + resources = querySpecRepository.findManyTargets(sourceId, fieldName, toQuerySpec(queryAdapter, targetResourceClass)); } else { resources = ((RelationshipRepository) relationshipRepository) .findManyTargets(sourceId, fieldName, toQueryParams(queryAdapter)); diff --git a/katharsis-core/src/main/java/io/katharsis/resource/registry/responseRepository/ResourceRepositoryAdapter.java b/katharsis-core/src/main/java/io/katharsis/resource/registry/responseRepository/ResourceRepositoryAdapter.java index cd4be790..78b9fbc1 100644 --- a/katharsis-core/src/main/java/io/katharsis/resource/registry/responseRepository/ResourceRepositoryAdapter.java +++ b/katharsis-core/src/main/java/io/katharsis/resource/registry/responseRepository/ResourceRepositoryAdapter.java @@ -35,7 +35,7 @@ public JsonApiResponse findOne(ID id, QueryAdapter queryAdapter) { resource = ((AnnotatedResourceRepositoryAdapter) resourceRepository).findOne(id, toQueryParams(queryAdapter)); } else if (resourceRepository instanceof QuerySpecResourceRepository) { - resource = ((QuerySpecResourceRepository) resourceRepository).findOne(id, toQuerySpec(queryAdapter)); + resource = ((QuerySpecResourceRepository) resourceRepository).findOne(id, toQuerySpec(queryAdapter, resourceInformation.getResourceClass())); } else { resource = ((ResourceRepository) resourceRepository).findOne(id, toQueryParams(queryAdapter)); @@ -49,7 +49,7 @@ public JsonApiResponse findAll(QueryAdapter queryAdapter) { resources = ((AnnotatedResourceRepositoryAdapter) resourceRepository).findAll(toQueryParams(queryAdapter)); } else if (resourceRepository instanceof QuerySpecResourceRepository) { - resources = ((QuerySpecResourceRepository) resourceRepository).findAll(toQuerySpec(queryAdapter)); + resources = ((QuerySpecResourceRepository) resourceRepository).findAll(toQuerySpec(queryAdapter, resourceInformation.getResourceClass())); } else { resources = ((ResourceRepository) resourceRepository).findAll(toQueryParams(queryAdapter)); @@ -63,7 +63,7 @@ public JsonApiResponse findAll(Iterable ids, QueryAdapter queryAdapter) { resources = ((AnnotatedResourceRepositoryAdapter) resourceRepository).findAll(ids, toQueryParams(queryAdapter)); } else if (resourceRepository instanceof QuerySpecResourceRepository) { - resources = ((QuerySpecResourceRepository) resourceRepository).findAll(ids, toQuerySpec(queryAdapter)); + resources = ((QuerySpecResourceRepository) resourceRepository).findAll(ids, toQuerySpec(queryAdapter, resourceInformation.getResourceClass())); } else { resources = ((ResourceRepository) resourceRepository).findAll(ids, toQueryParams(queryAdapter)); diff --git a/katharsis-core/src/main/java/io/katharsis/resource/registry/responseRepository/ResponseRepository.java b/katharsis-core/src/main/java/io/katharsis/resource/registry/responseRepository/ResponseRepository.java index d4f8f594..0f4a223f 100644 --- a/katharsis-core/src/main/java/io/katharsis/resource/registry/responseRepository/ResponseRepository.java +++ b/katharsis-core/src/main/java/io/katharsis/resource/registry/responseRepository/ResponseRepository.java @@ -83,7 +83,7 @@ private LinksInformation getLinksInformation(Object repository, Iterable reso return null; } - protected QuerySpec toQuerySpec(QueryAdapter queryAdapter) { + protected QuerySpec toQuerySpec(QueryAdapter queryAdapter, Class targetResourceClass) { if(queryAdapter == null) return null; if(queryAdapter instanceof QuerySpecAdapter){ @@ -98,8 +98,7 @@ protected QuerySpec toQuerySpec(QueryAdapter queryAdapter) { DefaultQuerySpecConverter converter = new DefaultQuerySpecConverter(resourceRegistry, operatorRegistry); - Class resourceClass = resourceInformation.getResourceClass(); - return converter.fromParams(resourceClass, queryParams); + return converter.fromParams(targetResourceClass, queryParams); } protected abstract FilterOperator getDefaultOperator() ; diff --git a/katharsis-jpa/src/main/java/io/katharsis/jpa/JpaRelationshipRepository.java b/katharsis-jpa/src/main/java/io/katharsis/jpa/JpaRelationshipRepository.java index 118e76a4..c234508c 100644 --- a/katharsis-jpa/src/main/java/io/katharsis/jpa/JpaRelationshipRepository.java +++ b/katharsis-jpa/src/main/java/io/katharsis/jpa/JpaRelationshipRepository.java @@ -182,8 +182,7 @@ private JpaQueryExecutor getExecutor(I sourceId, String fieldName, QuerySpec @Override public Class getSourceResourceClass() { - // TODO Auto-generated method stub - return null; + return entityClass; } @Override diff --git a/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/JoinRegistry.java b/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/JoinRegistry.java index b81d7cf1..ad61e78f 100644 --- a/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/JoinRegistry.java +++ b/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/JoinRegistry.java @@ -45,10 +45,11 @@ public E getEntityAttribute(MetaAttributePath attrPath) { criteriaPath = joinMap(currentCriteriaPath, pathElement); } else { // we may need to downcast if attribute is defined on a subtype - Class entityType = pathElement.getParent().asDataObject().getImplementationClass(); - boolean isSubType = !entityType.isAssignableFrom(backend.getJavaType(currentCriteriaPath)); + Class pathType = pathElement.getParent().asDataObject().getImplementationClass(); + Class currentType = backend.getJavaElementType(currentCriteriaPath); + boolean isSubType = !pathType.isAssignableFrom(currentType); if (isSubType) { - currentCriteriaPath = backend.joinSubType(currentCriteriaPath, entityType); + currentCriteriaPath = backend.joinSubType(currentCriteriaPath, pathType); } criteriaPath = backend.getAttribute(currentCriteriaPath, pathElement); } diff --git a/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/backend/JpaQueryBackend.java b/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/backend/JpaQueryBackend.java index b036701b..68e07d56 100644 --- a/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/backend/JpaQueryBackend.java +++ b/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/backend/JpaQueryBackend.java @@ -43,7 +43,7 @@ public interface JpaQueryBackend { public P or(List

predicates); - public Class getJavaType(E currentCriteriaPath); + public Class getJavaElementType(E currentCriteriaPath); public E getAttribute(E currentCriteriaPath, MetaAttribute pathElement); diff --git a/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/backend/criteria/JpaCriteriaQueryBackend.java b/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/backend/criteria/JpaCriteriaQueryBackend.java index 04467445..86f5c3a5 100644 --- a/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/backend/criteria/JpaCriteriaQueryBackend.java +++ b/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/backend/criteria/JpaCriteriaQueryBackend.java @@ -281,7 +281,7 @@ public Expression joinMapKey(Expression currentCriteriaPath, MetaAttribute } @Override - public Class getJavaType(Expression currentCriteriaPath) { + public Class getJavaElementType(Expression currentCriteriaPath) { return currentCriteriaPath.getJavaType(); } diff --git a/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/backend/querydsl/QuerydslQueryBackend.java b/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/backend/querydsl/QuerydslQueryBackend.java index 185ea698..74314ff4 100644 --- a/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/backend/querydsl/QuerydslQueryBackend.java +++ b/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/backend/querydsl/QuerydslQueryBackend.java @@ -8,6 +8,7 @@ import javax.persistence.criteria.JoinType; import com.google.common.collect.ImmutableList; +import com.querydsl.core.types.CollectionExpression; import com.querydsl.core.types.EntityPath; import com.querydsl.core.types.Expression; import com.querydsl.core.types.ExpressionUtils; @@ -15,9 +16,11 @@ import com.querydsl.core.types.Ops; import com.querydsl.core.types.Order; import com.querydsl.core.types.OrderSpecifier; +import com.querydsl.core.types.Path; import com.querydsl.core.types.Predicate; import com.querydsl.core.types.QTuple; import com.querydsl.core.types.dsl.BeanPath; +import com.querydsl.core.types.dsl.CollectionExpressionBase; import com.querydsl.core.types.dsl.ComparableExpression; import com.querydsl.core.types.dsl.LiteralExpression; import com.querydsl.core.types.dsl.MapExpressionBase; @@ -41,13 +44,16 @@ import io.katharsis.queryspec.FilterOperator; @SuppressWarnings({ "rawtypes", "unchecked" }) -public class QuerydslQueryBackend - implements JpaQueryBackend, OrderSpecifier, Predicate, Expression> { +public class QuerydslQueryBackend implements JpaQueryBackend, OrderSpecifier, Predicate, Expression> { private JoinRegistry, Expression> joinHelper; - private EntityPath root; + + private Path root; + private EntityPath parentFrom; + private QuerydslQueryImpl queryImpl; + private JPAQuery querydslQuery; private List> orderList = new ArrayList<>(); @@ -60,17 +66,27 @@ public QuerydslQueryBackend(QuerydslQueryImpl queryImpl, Class clazz, Clas if (parentEntityClass != null) { parentFrom = QuerydslUtils.getEntityPath(parentEntityClass); - root = (EntityPath) QuerydslUtils.get(parentFrom, parentAttr.getName()); + root = QuerydslUtils.getEntityPath(clazz); + + Path joinPath = (Path) QuerydslUtils.get(parentFrom, parentAttr.getName()); joinHelper = new JoinRegistry<>(this, queryImpl); + joinHelper.putJoin(new MetaAttributePath(), root); querydslQuery = queryFactory.select(root); querydslQuery = querydslQuery.from(parentFrom); - } else { + if (joinPath instanceof CollectionExpression) { + querydslQuery = querydslQuery.join((CollectionExpression) joinPath, root); + } + else { + querydslQuery = querydslQuery.join((EntityPath) joinPath, root); + } + } + else { root = QuerydslUtils.getEntityPath(clazz); joinHelper = new JoinRegistry<>(this, queryImpl); joinHelper.putJoin(new MetaAttributePath(), root); querydslQuery = queryFactory.select(root); - querydslQuery = querydslQuery.from(root); + querydslQuery = querydslQuery.from((EntityPath) root); } } @@ -93,7 +109,7 @@ public void addPredicate(Predicate predicate) { } @Override - public EntityPath getRoot() { + public Path getRoot() { return root; } @@ -111,7 +127,8 @@ public List> getOrderList() { public OrderSpecifier newSort(Expression expr, Direction dir) { if (dir == Direction.ASC) { return new OrderSpecifier(Order.ASC, expr); - } else { + } + else { return new OrderSpecifier(Order.DESC, expr); } } @@ -124,8 +141,7 @@ public void distinct() { @Override public void addParentPredicate(MetaAttribute primaryKeyAttr) { List parentIds = queryImpl.getParentIds(); - SimpleExpression parentIdPath = (SimpleExpression) QuerydslUtils.get(parentFrom, - primaryKeyAttr.getName()); + SimpleExpression parentIdPath = (SimpleExpression) QuerydslUtils.get(parentFrom, primaryKeyAttr.getName()); addPredicate(parentIdPath.in((List) parentIds)); } @@ -142,7 +158,8 @@ public void addSelection(Expression expression, String name) { if (selection != null) { if (selection instanceof QTuple) { newSelection.addAll(((QTuple) selection).getArgs()); - } else { + } + else { newSelection.add(selection); } } @@ -178,37 +195,49 @@ public Predicate buildPredicate(FilterOperator operator, Expression expressio private Predicate handle(Expression expression, FilterOperator operator, Object value) { // NOSONAR if (operator == FilterOperator.EQ || operator == FilterOperator.NEQ) { return handleEquals(expression, operator, value); - } else if (operator == JpaFilterOperators.LIKE) { + } + else if (operator == JpaFilterOperators.LIKE) { return ((StringExpression) expression).like(value.toString()); - } else if (operator == JpaFilterOperators.NOT_LIKE) { + } + else if (operator == JpaFilterOperators.NOT_LIKE) { return ((StringExpression) expression).like(value.toString()).not(); - } else if (operator == JpaFilterOperators.ILIKE) { + } + else if (operator == JpaFilterOperators.ILIKE) { return ((StringExpression) expression).lower().like(value.toString().toLowerCase()); - } else if (operator == FilterOperator.GT) { + } + else if (operator == FilterOperator.GT) { if (expression instanceof NumberExpression) { return ((NumberExpression) expression).gt((Number) value); - } else { + } + else { return ((ComparableExpression) expression).gt((Comparable) value); } - } else if (operator == FilterOperator.LT) { + } + else if (operator == FilterOperator.LT) { if (expression instanceof NumberExpression) { return ((NumberExpression) expression).lt((Number) value); - } else { + } + else { return ((ComparableExpression) expression).lt((Comparable) value); } - } else if (operator == FilterOperator.GE) { + } + else if (operator == FilterOperator.GE) { if (expression instanceof NumberExpression) { return ((NumberExpression) expression).goe((Number) value); - } else { + } + else { return ((ComparableExpression) expression).goe((Comparable) value); } - } else if (operator == FilterOperator.LE) { + } + else if (operator == FilterOperator.LE) { if (expression instanceof NumberExpression) { return ((NumberExpression) expression).loe((Number) value); - } else { + } + else { return ((ComparableExpression) expression).loe((Comparable) value); } - } else { + } + else { throw new IllegalStateException("unexpected operator " + operator); } @@ -218,15 +247,18 @@ private Predicate handleEquals(Expression expression, FilterOperator operator if (value instanceof List) { Predicate p = ((SimpleExpression) expression).in((List) value); return negateIfNeeded(p, operator); - } else if (Collection.class.isAssignableFrom(expression.getType())) { + } + else if (Collection.class.isAssignableFrom(expression.getType())) { SimpleExpression simpleExpr = (SimpleExpression) expression; Predicate p = simpleExpr.in(value); return negateIfNeeded(p, operator); - } else if (expression instanceof MapExpressionBase) { + } + else if (expression instanceof MapExpressionBase) { MapExpressionBase mapExpression = (MapExpressionBase) expression; Predicate p = mapExpression.containsValue(value); return negateIfNeeded(p, operator); - } else if (value == null) { + } + else if (value == null) { return negateIfNeeded(((SimpleExpression) expression).isNull(), operator); } return negateIfNeeded(((SimpleExpression) expression).eq(value), operator); @@ -237,7 +269,8 @@ private Expression handleConversions(Expression expression, FilterOperator if (expression.getType() != String.class && (operator == JpaFilterOperators.LIKE || operator == JpaFilterOperators.ILIKE)) { return ((LiteralExpression) expression).stringValue(); - } else { + } + else { return expression; } } @@ -246,7 +279,8 @@ private Expression handleConversions(Expression expression, FilterOperator public Predicate and(List predicates) { if (predicates.size() == 1) { return predicates.get(0); - } else { + } + else { return new BooleanPredicateOperation(Ops.AND, (ImmutableList) ImmutableList.copyOf(predicates)); } } @@ -260,7 +294,8 @@ public Predicate not(Predicate predicate) { public Predicate or(List predicates) { if (predicates.size() == 1) { return predicates.get(0); - } else { + } + else { return new BooleanPredicateOperation(Ops.OR, (ImmutableList) ImmutableList.copyOf(predicates)); } } @@ -312,7 +347,10 @@ public Expression joinMapKey(Expression currentCriteriaPath, MetaAttribute } @Override - public Class getJavaType(Expression expression) { + public Class getJavaElementType(Expression expression) { + if (expression instanceof CollectionExpressionBase) { + return ((CollectionExpressionBase) expression).getElementType(); + } return expression.getType(); } @@ -323,7 +361,8 @@ public Expression getAttribute(final Expression expression, MetaAttribute QuerydslExpressionFactory expressionFactory = (QuerydslExpressionFactory) virtualAttrs .get((MetaVirtualAttribute) pathElement); return expressionFactory.getExpression(expression, getQuery()); - } else { + } + else { return QuerydslUtils.get(expression, pathElement.getName()); } } @@ -344,7 +383,8 @@ public Expression doJoin(MetaAttribute targetAttr, JoinType joinType, Express .get(virtualAttr); return expressionFactory.getExpression(parent, getQuery()); - } else { + } + else { Expression expression = QuerydslUtils.get(parent, targetAttr.getName()); querydslQuery.getMetadata().addJoin(QuerydslUtils.convertJoinType(joinType), expression); return expression; diff --git a/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/backend/querydsl/QuerydslUtils.java b/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/backend/querydsl/QuerydslUtils.java index 1de40537..7bcc94ee 100644 --- a/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/backend/querydsl/QuerydslUtils.java +++ b/katharsis-jpa/src/main/java/io/katharsis/jpa/internal/query/backend/querydsl/QuerydslUtils.java @@ -23,32 +23,34 @@ public static EntityPath getEntityPath(Class entityClass) { String fieldName = firstToLower(entityClass.getSimpleName()); Field field = queryClass.getField(fieldName); return (EntityPath) field.get(entityClass); - } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { + } + catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { throw new IllegalStateException("failed to access query class " + queryClass.getName(), e); } } @SuppressWarnings("unchecked") - public static Expression get(Expression entityPath, String name) { + public static Expression get(Expression path, String name) { try { - Class clazz = entityPath.getClass(); + Class clazz = path.getClass(); Field field = clazz.getField(name); - return (Expression) field.get(entityPath); - } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { - throw new IllegalStateException("failed get field " + entityPath + "." + name, e); + return (Expression) field.get(path); + } + catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { + throw new IllegalStateException("failed get field " + path + "." + name, e); } } public static com.querydsl.core.JoinType convertJoinType(JoinType joinType) { switch (joinType) { - case INNER: - return com.querydsl.core.JoinType.JOIN; - case LEFT: - return com.querydsl.core.JoinType.LEFTJOIN; - case RIGHT: - return com.querydsl.core.JoinType.RIGHTJOIN; - default: - throw new IllegalStateException(joinType.toString() + " unknown"); + case INNER: + return com.querydsl.core.JoinType.JOIN; + case LEFT: + return com.querydsl.core.JoinType.LEFTJOIN; + case RIGHT: + return com.querydsl.core.JoinType.RIGHTJOIN; + default: + throw new IllegalStateException(joinType.toString() + " unknown"); } } @@ -70,7 +72,8 @@ public static Class getQueryClass(Class entityClass) { String queryClassName = entityClass.getPackage().getName() + ".Q" + entityClass.getSimpleName(); try { return entityClass.getClassLoader().loadClass(queryClassName); - } catch (ClassNotFoundException | SecurityException | IllegalArgumentException e) { + } + catch (ClassNotFoundException | SecurityException | IllegalArgumentException e) { throw new IllegalStateException("unable to find query class " + queryClassName, e); } } diff --git a/katharsis-jpa/src/test/java/io/katharsis/jpa/AbstractJpaJerseyTest.java b/katharsis-jpa/src/test/java/io/katharsis/jpa/AbstractJpaJerseyTest.java index 832a083b..8408b828 100644 --- a/katharsis-jpa/src/test/java/io/katharsis/jpa/AbstractJpaJerseyTest.java +++ b/katharsis-jpa/src/test/java/io/katharsis/jpa/AbstractJpaJerseyTest.java @@ -20,6 +20,7 @@ import io.katharsis.client.KatharsisClient; import io.katharsis.jpa.model.TestEntity; import io.katharsis.jpa.query.AbstractJpaTest; +import io.katharsis.jpa.query.querydsl.QuerydslQueryFactory; import io.katharsis.jpa.util.EntityManagerProducer; import io.katharsis.jpa.util.SpringTransactionRunner; import io.katharsis.jpa.util.TestConfig; @@ -95,6 +96,7 @@ public TestApplication() { new QueryParamsBuilder(new DefaultQueryParamsParser()), new SampleJsonServiceLocator()); JpaModule module = new JpaModule(emFactory, em, transactionRunner); + module.setQueryFactory(QuerydslQueryFactory.newInstance(module.getMetaLookup(), em)); setupModule(module); feature.addModule(module); diff --git a/katharsis-jpa/src/test/java/io/katharsis/jpa/JpaQuerySpecEndToEndTest.java b/katharsis-jpa/src/test/java/io/katharsis/jpa/JpaQuerySpecEndToEndTest.java index 2c3c812c..d46a8981 100644 --- a/katharsis-jpa/src/test/java/io/katharsis/jpa/JpaQuerySpecEndToEndTest.java +++ b/katharsis-jpa/src/test/java/io/katharsis/jpa/JpaQuerySpecEndToEndTest.java @@ -8,6 +8,7 @@ import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import io.katharsis.client.QuerySpecRelationshipRepositoryStub; @@ -45,7 +46,22 @@ public void testIncludeRelations() throws InstantiationException, IllegalAccessE } @Test - public void testRelationRepoFindOneTarget() throws InstantiationException, IllegalAccessException { + public void testFindOneTargetWithNullResult() throws InstantiationException, IllegalAccessException { + TestEntity test = new TestEntity(); + test.setId(2L); + test.setStringValue("test"); + testRepo.save(test); + + QuerySpecRelationshipRepositoryStub relRepo = client + .getQuerySpecRepository(TestEntity.class, RelatedEntity.class); + + RelatedEntity related = relRepo.findOneTarget(test.getId(), TestEntity.ATTR_oneRelatedValue, + new QuerySpec(RelatedEntity.class)); + Assert.assertNull(related); + } + + @Test + public void testFindOneTarget() throws InstantiationException, IllegalAccessException { TestEntity test = addTestWithOneRelation(); QuerySpecRelationshipRepositoryStub relRepo = client @@ -54,7 +70,57 @@ public void testRelationRepoFindOneTarget() throws InstantiationException, Illeg RelatedEntity related = relRepo.findOneTarget(test.getId(), TestEntity.ATTR_oneRelatedValue, new QuerySpec(RelatedEntity.class)); Assert.assertNotNull(related); + } + + @Test + public void testAddManyRelationWithRelationshipRepository() throws InstantiationException, IllegalAccessException { + testAddManyRelation(false); + } + @Test + @Ignore + // TODO bidirectionality not properly handled, see + // ResourceUpsert should make use of relationship repositories #130 + public void testAddManyRelationWithResourceSave() throws InstantiationException, IllegalAccessException { + testAddManyRelation(true); + } + + private void testAddManyRelation(boolean onSave) throws InstantiationException, IllegalAccessException { + QuerySpecResourceRepositoryStub relatedRepo = client.getQuerySpecRepository(RelatedEntity.class); + RelatedEntity related1 = new RelatedEntity(); + related1.setId(1L); + related1.setStringValue("related1"); + relatedRepo.save(related1); + + RelatedEntity related2 = new RelatedEntity(); + related2.setId(2L); + related2.setStringValue("related2"); + relatedRepo.save(related2); + + TestEntity test = new TestEntity(); + test.setId(3L); + test.setStringValue("test"); + if (onSave) { + test.setManyRelatedValues(Arrays.asList(related1, related2)); + } + testRepo.save(test, includeManyRelatedValueParams()); + + // query relation + QuerySpecRelationshipRepositoryStub relRepo = client + .getQuerySpecRepository(TestEntity.class, RelatedEntity.class); + if (!onSave) { + relRepo.addRelations(test, Arrays.asList(1L, 2L), TestEntity.ATTR_manyRelatedValues); + } + List related = relRepo.findManyTargets(test.getId(), TestEntity.ATTR_manyRelatedValues, + new QuerySpec(RelatedEntity.class)); + Assert.assertEquals(2, related.size()); + + // query relation in opposite direction + QuerySpecRelationshipRepositoryStub backRelRepo = client + .getQuerySpecRepository(RelatedEntity.class, TestEntity.class); + test = backRelRepo.findOneTarget(2L, RelatedEntity.ATTR_testEntity, new QuerySpec(TestEntity.class)); + Assert.assertNotNull(test); + Assert.assertEquals(3L, test.getId().longValue()); } @Test @@ -160,6 +226,12 @@ private QuerySpec includeOneRelatedValueParams() { return querySpec; } + private QuerySpec includeManyRelatedValueParams() { + QuerySpec querySpec = new QuerySpec(TestEntity.class); + querySpec.includeRelation(Arrays.asList(TestEntity.ATTR_manyRelatedValues)); + return querySpec; + } + @Test public void testSaveOneRelation() { TestEntity test = addTestWithOneRelation(); diff --git a/katharsis-jpa/src/test/java/io/katharsis/jpa/repository/JpaRelationshipRepositoryTestBase.java b/katharsis-jpa/src/test/java/io/katharsis/jpa/repository/JpaRelationshipRepositoryTestBase.java index b460152a..018fdff4 100644 --- a/katharsis-jpa/src/test/java/io/katharsis/jpa/repository/JpaRelationshipRepositoryTestBase.java +++ b/katharsis-jpa/src/test/java/io/katharsis/jpa/repository/JpaRelationshipRepositoryTestBase.java @@ -6,10 +6,7 @@ import java.util.List; import org.hamcrest.core.Is; -import org.hamcrest.core.IsInstanceOf; -import org.hamcrest.core.IsNot; import org.junit.Assert; -import org.junit.Assume; import org.junit.Before; import org.junit.Test; import org.springframework.transaction.annotation.Transactional; @@ -18,7 +15,6 @@ import io.katharsis.jpa.model.RelatedEntity; import io.katharsis.jpa.model.TestEntity; import io.katharsis.jpa.query.AbstractJpaTest; -import io.katharsis.jpa.query.querydsl.QuerydslQueryFactory; import io.katharsis.queryspec.FilterOperator; import io.katharsis.queryspec.FilterSpec; import io.katharsis.queryspec.QuerySpec; @@ -156,9 +152,6 @@ public void testSetRelation() throws InstantiationException, IllegalAccessExcept @Test public void testGetManyRelation() { - //TODO fix for QueryDSL - Assume.assumeThat("QueryDSL still breaks on this, so ignore it for now", - queryFactory, IsNot.not(IsInstanceOf.instanceOf(QuerydslQueryFactory.class))); TestEntity test = em.find(TestEntity.class, 1L); Assert.assertThat(test.getManyRelatedValues().size(), Is.is(0));