DATAJPA-689 - Allow @EntityGraph on CrudRepository.findOne(…).

We now honor @EntityGraph definitions on CrudRepository.findOne(…) which was previously only the case for methods that created a Query explicitly. 

Extracted tryGetFetchGraphHints(…) method from tryConfigureFetchGraph(…) method in Jpa21Utils to allow EntityGraph hints to be used in SimpleJpaRepository.findOne(…). Construction of query hints from context information in SimpleJpaRepository is now performed via the getQueryHints(…) method. Adjusted QueryDslJpaRepository to use query hints as well.

Added unit and integration tests to verify that @EntityGraph information is propagated to findOne executions.

Original pull request: #137.
This commit is contained in:
Thomas Darimont
2015-03-09 18:27:56 +01:00
committed by Oliver Gierke
parent febd41b10b
commit d07aeae814
8 changed files with 134 additions and 49 deletions

View File

@@ -48,12 +48,15 @@ public class EntityGraphRepositoryMethodsIntegrationTests {
@Autowired RepositoryMethodsWithEntityGraphConfigJpaRepository repository;
User tom;
User olli;
Role role;
@Before
public void setup() {
tom = new User("Thomas", "Darimont", "tdarimont@example.org");
olli = new User("Oliver", "Gierke", "ogierke@example.org");
role = new Role("Developer");
em.persist(role);
tom.getRoles().add(role);
@@ -75,4 +78,25 @@ public class EntityGraphRepositoryMethodsIntegrationTests {
assertThat(Persistence.getPersistenceUtil().isLoaded(result.get(0).getRoles()), is(true));
assertThat(result.get(0), is(tom));
}
/**
* @see DATAJPA-689
*/
@Test
public void shouldRespectConfiguredJpaEntityGraphInFindOne() {
Assume.assumeTrue(currentEntityManagerIsAJpa21EntityManager(em));
olli = repository.save(olli);
tom.getColleagues().add(olli);
tom = repository.save(tom);
em.flush();
User user = repository.findOne(tom.getId());
assertThat(user, is(notNullValue()));
assertThat("colleages should be fetched with 'user.detail' fetchgraph",
Persistence.getPersistenceUtil().isLoaded(user.getColleagues()), is(true));
}
}

View File

@@ -345,6 +345,19 @@ public class JpaQueryMethodUnitTests {
assertThat(method.getEntityGraph().getType(), is(EntityGraphType.FETCH));
}
/**
* @see DATAJPA-689
*/
@Test
public void shouldFindEntityGraphAnnotationOnOverriddenSimpleJpaRepositoryMethodFindOne() throws Exception {
JpaQueryMethod method = new JpaQueryMethod(JpaRepositoryOverride.class.getMethod("findOne"), metadata, extractor);
assertThat(method.getEntityGraph(), is(notNullValue()));
assertThat(method.getEntityGraph().getName(), is("User.detail"));
assertThat(method.getEntityGraph().getType(), is(EntityGraphType.FETCH));
}
/**
* Interface to define invalid repository methods for testing.
*
@@ -414,7 +427,13 @@ public class JpaQueryMethodUnitTests {
*/
@Override
@EntityGraph("User.detail")
public List<User> findAll();
List<User> findAll();
/**
* DATAJPA-689
*/
@EntityGraph("User.detail")
User findOne();
}
@Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,16 +23,22 @@ import org.springframework.data.jpa.repository.EntityGraph.EntityGraphType;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* Custom repository interface that customizes the fetching behavior of querys of well known repository interface methods via {@link EntityGraph}
* annotation.
* Custom repository interface that customizes the fetching behavior of querys of well known repository interface
* methods via {@link EntityGraph} annotation.
*
* @author Thomas Darimont
*/
public interface RepositoryMethodsWithEntityGraphConfigJpaRepository extends JpaRepository<User, Long> {
public interface RepositoryMethodsWithEntityGraphConfigJpaRepository extends JpaRepository<User, Integer> {
/**
* Should find all users.
*/
@EntityGraph(type = EntityGraphType.LOAD, value = "User.overview")
List<User> findAll();
/**
* Should fetch all user details
*/
@EntityGraph(type = EntityGraphType.FETCH, value = "User.detail")
User findOne(Integer id);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2014 the original author or authors.
* Copyright 2011-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,10 @@
*/
package org.springframework.data.jpa.repository.support;
import static java.util.Collections.*;
import static org.mockito.Mockito.*;
import javax.persistence.EntityGraph;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
@@ -30,16 +32,19 @@ import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.sample.User;
import org.springframework.data.jpa.repository.EntityGraph.EntityGraphType;
import org.springframework.data.jpa.repository.query.JpaEntityGraph;
/**
* Unit tests for {@link SimpleJpaRepository}.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
@RunWith(MockitoJUnitRunner.class)
public class SimpleJpaRepositoryUnitTests {
SimpleJpaRepository<User, Long> repo;
SimpleJpaRepository<User, Integer> repo;
@Mock EntityManager em;
@Mock CriteriaBuilder builder;
@@ -49,6 +54,7 @@ public class SimpleJpaRepositoryUnitTests {
@Mock TypedQuery<Long> countQuery;
@Mock JpaEntityInformation<User, Long> information;
@Mock CrudMethodMetadata metadata;
@Mock EntityGraph<User> entityGraph;
@Before
public void setUp() {
@@ -64,7 +70,7 @@ public class SimpleJpaRepositoryUnitTests {
when(em.createQuery(criteriaQuery)).thenReturn(query);
when(em.createQuery(countCriteriaQuery)).thenReturn(countQuery);
repo = new SimpleJpaRepository<User, Long>(information, em);
repo = new SimpleJpaRepository<User, Integer>(information, em);
repo.setRepositoryMethodMetadata(metadata);
}
@@ -86,6 +92,23 @@ public class SimpleJpaRepositoryUnitTests {
@Test(expected = EmptyResultDataAccessException.class)
public void throwsExceptionIfEntityToDeleteDoesNotExist() {
repo.delete(4711L);
repo.delete(4711);
}
/**
* @see DATAJPA-689
*/
@Test
@SuppressWarnings({ "rawtypes", "unchecked" })
public void shouldPropagateConfiguredEntityGraphToFindOne() {
String entityGraphName = "User.detail";
when(metadata.getEntityGraph()).thenReturn(new JpaEntityGraph(entityGraphName, EntityGraphType.LOAD));
when(em.getEntityGraph(entityGraphName)).thenReturn((EntityGraph) entityGraph);
Integer id = 0;
repo.findOne(id);
verify(em).find(User.class, id, singletonMap(EntityGraphType.LOAD.getKey(), (Object) entityGraph));
}
}