/*
* Copyright 2008-2017 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.jpa.repository.query;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import static org.springframework.data.jpa.support.EntityManagerTestUtils.*;
import java.lang.reflect.Method;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.QueryHint;
import javax.persistence.TypedQuery;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.data.jpa.domain.sample.User;
import org.springframework.data.jpa.provider.PersistenceProvider;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.EntityGraph.EntityGraphType;
import org.springframework.data.jpa.repository.Lock;
import org.springframework.data.jpa.repository.QueryHints;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
/**
* Integration test for {@link AbstractJpaQuery}.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:infrastructure.xml")
public class AbstractJpaQueryTests {
@PersistenceContext EntityManager em;
Query query;
TypedQuery<Long> countQuery;
@Before
@SuppressWarnings("unchecked")
public void setUp() {
query = mock(Query.class);
countQuery = mock(TypedQuery.class);
}
@Test // DATADOC-97
public void addsHintsToQueryObject() throws Exception {
JpaQueryMethod queryMethod = getMethod("findByLastname", String.class);
AbstractJpaQuery jpaQuery = new DummyJpaQuery(queryMethod, em);
Query result = jpaQuery.createQuery(new Object[] { "Matthews" });
verify(result).setHint("foo", "bar");
result = jpaQuery.createCountQuery(new Object[] { "Matthews" });
verify(result).setHint("foo", "bar");
}
@Test // DATAJPA-54
public void skipsHintsForCountQueryIfConfigured() throws Exception {
JpaQueryMethod queryMethod = getMethod("findByFirstname", String.class);
AbstractJpaQuery jpaQuery = new DummyJpaQuery(queryMethod, em);
Query result = jpaQuery.createQuery(new Object[] { "Dave" });
verify(result).setHint("bar", "foo");
result = jpaQuery.createCountQuery(new Object[] { "Dave" });
verify(result, never()).setHint("bar", "foo");
}
@Test // DATAJPA-73
public void addsLockingModeToQueryObject() throws Exception {
when(query.setLockMode(any(LockModeType.class))).thenReturn(query);
JpaQueryMethod queryMethod = getMethod("findOneLocked", Integer.class);
AbstractJpaQuery jpaQuery = new DummyJpaQuery(queryMethod, em);
Query result = jpaQuery.createQuery(new Object[] { Integer.valueOf(1) });
verify(result).setLockMode(LockModeType.PESSIMISTIC_WRITE);
}
@Test // DATAJPA-466
@Transactional
public void shouldAddEntityGraphHintForFetch() throws Exception {
Assume.assumeTrue(currentEntityManagerIsAJpa21EntityManager(em));
JpaQueryMethod queryMethod = getMethod("findAll");
javax.persistence.EntityGraph<?> entityGraph = em.getEntityGraph("User.overview");
AbstractJpaQuery jpaQuery = new DummyJpaQuery(queryMethod, em);
Query result = jpaQuery.createQuery(new Object[0]);
verify(result).setHint("javax.persistence.fetchgraph", entityGraph);
}
@Test // DATAJPA-466
@Transactional
public void shouldAddEntityGraphHintForLoad() throws Exception {
Assume.assumeTrue(currentEntityManagerIsAJpa21EntityManager(em));
JpaQueryMethod queryMethod = getMethod("getById", Integer.class);
javax.persistence.EntityGraph<?> entityGraph = em.getEntityGraph("User.detail");
AbstractJpaQuery jpaQuery = new DummyJpaQuery(queryMethod, em);
Query result = jpaQuery.createQuery(new Object[] { 1 });
verify(result).setHint("javax.persistence.loadgraph", entityGraph);
}
private JpaQueryMethod getMethod(String name, Class<?>... parameterTypes) throws Exception {
Method method = SampleRepository.class.getMethod(name, parameterTypes);
PersistenceProvider persistenceProvider = PersistenceProvider.fromEntityManager(em);
return new JpaQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
new SpelAwareProxyProjectionFactory(), persistenceProvider);
}
interface SampleRepository extends Repository<User, Integer> {
@QueryHints({ @QueryHint(name = "foo", value = "bar") })
List<User> findByLastname(String lastname);
@QueryHints(value = { @QueryHint(name = "bar", value = "foo") }, forCounting = false)
List<User> findByFirstname(String firstname);
@Lock(LockModeType.PESSIMISTIC_WRITE)
@org.springframework.data.jpa.repository.Query("select u from User u where u.id = ?1")
List<User> findOneLocked(Integer primaryKey);
// DATAJPA-466
@EntityGraph(value = "User.detail", type = EntityGraphType.LOAD)
User getById(Integer id);
// DATAJPA-466
@EntityGraph("User.overview")
List<User> findAll();
}
class DummyJpaQuery extends AbstractJpaQuery {
public DummyJpaQuery(JpaQueryMethod method, EntityManager em) {
super(method, em);
}
@Override
protected Query doCreateQuery(Object[] values) {
return query;
}
@Override
protected TypedQuery<Long> doCreateCountQuery(Object[] values) {
return (TypedQuery<Long>) countQuery;
}
}
}