Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Further improvements to QueryDsl support.
- use correct Maven phase to generate query classes - use target folder that compiler plugin automatically picks up - added constructor taking an EntityPath to QueryDslJpaRepository - create PathBuilder upfront and reuse it - use Pageable.getOffset() - let test case use QUser directly - added test case to ensure detection of query class - added QueryDslRepositorySupport to ease implementation of repositories
- Loading branch information
Showing
5 changed files
with
268 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
88 changes: 88 additions & 0 deletions
88
src/main/java/org/springframework/data/jpa/repository/support/QueryDslRepositorySupport.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package org.springframework.data.jpa.repository.support; | ||
|
||
import javax.annotation.PostConstruct; | ||
import javax.persistence.EntityManager; | ||
import javax.persistence.PersistenceContext; | ||
|
||
import org.springframework.beans.factory.annotation.Required; | ||
import org.springframework.stereotype.Repository; | ||
import org.springframework.util.Assert; | ||
|
||
import com.mysema.query.dml.DeleteClause; | ||
import com.mysema.query.dml.UpdateClause; | ||
import com.mysema.query.jpa.JPQLQuery; | ||
import com.mysema.query.jpa.impl.JPADeleteClause; | ||
import com.mysema.query.jpa.impl.JPAQuery; | ||
import com.mysema.query.jpa.impl.JPAUpdateClause; | ||
import com.mysema.query.types.EntityPath; | ||
|
||
|
||
/** | ||
* Base class for implementing repositories using QueryDsl library. | ||
* | ||
* @author Oliver Gierke | ||
*/ | ||
@Repository | ||
public abstract class QueryDslRepositorySupport { | ||
|
||
@PersistenceContext | ||
private EntityManager entityManager; | ||
|
||
|
||
/** | ||
* Setter to inject {@link EntityManager}. | ||
* | ||
* @param entityManager must not be {@literal null} | ||
*/ | ||
@Required | ||
public void setEntityManager(EntityManager entityManager) { | ||
|
||
Assert.notNull(entityManager); | ||
this.entityManager = entityManager; | ||
} | ||
|
||
|
||
/** | ||
* Callback to verify configuration. Used by containers. | ||
*/ | ||
@PostConstruct | ||
public void validate() { | ||
|
||
Assert.notNull(entityManager, "EntityManager must not be null!"); | ||
} | ||
|
||
|
||
/** | ||
* Returns a fresh {@link JPQLQuery}. | ||
* | ||
* @return | ||
*/ | ||
protected JPQLQuery from(EntityPath<?>... paths) { | ||
|
||
return new JPAQuery(entityManager).from(paths); | ||
} | ||
|
||
|
||
/** | ||
* Returns a fresh {@link DeleteClause}. | ||
* | ||
* @param path | ||
* @return | ||
*/ | ||
protected DeleteClause<JPADeleteClause> delete(EntityPath<?> path) { | ||
|
||
return new JPADeleteClause(entityManager, path); | ||
} | ||
|
||
|
||
/** | ||
* Returns a fresh {@link UpdateClause}. | ||
* | ||
* @param path | ||
* @return | ||
*/ | ||
protected UpdateClause<JPAUpdateClause> update(EntityPath<?> path) { | ||
|
||
return new JPAUpdateClause(entityManager, path); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
142 changes: 142 additions & 0 deletions
142
.../java/org/springframework/data/jpa/repository/support/QueryDslRepositorySupportTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
package org.springframework.data.jpa.repository.support; | ||
|
||
import static org.hamcrest.Matchers.*; | ||
import static org.junit.Assert.*; | ||
|
||
import java.util.List; | ||
|
||
import javax.persistence.EntityManager; | ||
import javax.persistence.PersistenceContext; | ||
|
||
import org.junit.Before; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
import org.springframework.data.jpa.domain.sample.QUser; | ||
import org.springframework.data.jpa.domain.sample.User; | ||
import org.springframework.test.context.ContextConfiguration; | ||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
|
||
/** | ||
* Integration test for {@link QueryDslRepositorySupport}. | ||
* | ||
* @author Oliver Gierke | ||
*/ | ||
@RunWith(SpringJUnit4ClassRunner.class) | ||
@ContextConfiguration({ "classpath:infrastructure.xml" }) | ||
@Transactional | ||
public class QueryDslRepositorySupportTests { | ||
|
||
@PersistenceContext | ||
EntityManager em; | ||
|
||
UserRepository repository; | ||
User dave, carter; | ||
|
||
|
||
@Before | ||
public void setup() { | ||
|
||
dave = new User("Dave", "Matthews", "dave@matthews.com"); | ||
em.persist(dave); | ||
|
||
carter = new User("Carter", "Beauford", "carter@beauford.com"); | ||
em.persist(carter); | ||
|
||
UserRepositoryImpl repository = new UserRepositoryImpl(); | ||
repository.setEntityManager(em); | ||
repository.validate(); | ||
|
||
this.repository = repository; | ||
} | ||
|
||
|
||
@Test | ||
public void readsUsersCorrectly() throws Exception { | ||
|
||
List<User> result = repository.findUsersByLastname("Matthews"); | ||
assertThat(result.size(), is(1)); | ||
assertThat(result.get(0), is(dave)); | ||
|
||
result = repository.findUsersByLastname("Beauford"); | ||
assertThat(result.size(), is(1)); | ||
assertThat(result.get(0), is(carter)); | ||
} | ||
|
||
|
||
@Test | ||
public void updatesUsersCorrectly() throws Exception { | ||
|
||
long updates = repository.updateLastnamesTo("Foo"); | ||
assertThat(updates, is(2L)); | ||
|
||
List<User> result = repository.findUsersByLastname("Matthews"); | ||
assertThat(result.size(), is(0)); | ||
|
||
result = repository.findUsersByLastname("Beauford"); | ||
assertThat(result.size(), is(0)); | ||
|
||
result = repository.findUsersByLastname("Foo"); | ||
assertThat(result.size(), is(2)); | ||
assertThat(result, hasItems(dave, carter)); | ||
} | ||
|
||
|
||
@Test | ||
public void deletesAllWithLastnameCorrectly() throws Exception { | ||
|
||
long updates = repository.deleteAllWithLastname("Matthews"); | ||
assertThat(updates, is(1L)); | ||
|
||
List<User> result = repository.findUsersByLastname("Matthews"); | ||
assertThat(result.size(), is(0)); | ||
|
||
result = repository.findUsersByLastname("Beauford"); | ||
assertThat(result.size(), is(1)); | ||
assertThat(result.get(0), is(carter)); | ||
} | ||
|
||
|
||
@Test(expected = IllegalArgumentException.class) | ||
public void rejectsUnsetEntityManager() throws Exception { | ||
|
||
UserRepositoryImpl repositoryImpl = new UserRepositoryImpl(); | ||
repositoryImpl.validate(); | ||
} | ||
|
||
private static interface UserRepository { | ||
|
||
List<User> findUsersByLastname(String firstname); | ||
|
||
|
||
long updateLastnamesTo(String lastname); | ||
|
||
|
||
long deleteAllWithLastname(String lastname); | ||
} | ||
|
||
private static class UserRepositoryImpl extends QueryDslRepositorySupport | ||
implements UserRepository { | ||
|
||
private static final QUser user = QUser.user; | ||
|
||
|
||
public List<User> findUsersByLastname(String lastname) { | ||
|
||
return from(user).where(user.lastname.eq(lastname)).list(user); | ||
} | ||
|
||
|
||
public long updateLastnamesTo(String lastname) { | ||
|
||
return update(user).set(user.lastname, lastname).execute(); | ||
} | ||
|
||
|
||
public long deleteAllWithLastname(String lastname) { | ||
|
||
return delete(user).where(user.lastname.eq(lastname)).execute(); | ||
} | ||
} | ||
} |