diff --git a/src/docbkx/reference/jpa.xml b/src/docbkx/reference/jpa.xml index 70d640321..25c503433 100644 --- a/src/docbkx/reference/jpa.xml +++ b/src/docbkx/reference/jpa.xml @@ -76,7 +76,7 @@ transaction-manager-ref - Explicitly wire tha + Explicitly wire the PlatformTransactionManager to be used with the repositories being detected by the repositories element. Usually only necessary if @@ -489,7 +489,7 @@ public class User { All the sections above describe how to declare queries to access a given entity or collection of entities. Of course you can add custom modifying behaviour by using facilities described in . As this approach is feasible for + linkend="repositories.custom-implementations" />. As this approach is feasible for comprehensive custom functionality, you can achieve the execution of modifying queries that actually only need parameter binding by annotating the query method with @Modifying: @@ -546,20 +546,14 @@ int setFixedFirstnameFor(String firstname, String lastname);
- - Specifications - - JPA 2 introduces a criteria API that can be used to build queries programmatically. Writing a criteria you actually define the where-clause of a query for a domain class. Taking another step back these criteria can be regarded as predicate over the entity that is described by the JPA criteria API constraints. - - Spring Data JPA takes the concept of a specification from Eric Evans' book "Domain Driven Design", following the same semantics and providing an API to define such @@ -568,14 +562,10 @@ int setFixedFirstnameFor(String firstname, String lastname); the JpaSpecificationExecutor interface: - - public interface CustomerRepository extends CrudRepository<Customer, Long>, JpaSpecificationExecutor { … } - - The additional interface carries methods that allow you to execute Specifications in a variety of ways. @@ -587,20 +577,14 @@ int setFixedFirstnameFor(String firstname, String lastname); List<T> readAll(Specification<T> spec); - - The Specification interface is as follows: - - public interface Specification<T> { Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder); } - - Okay, so what is the typical use case? Specifications can easily be used to build an extensible set of predicates on top of an entity that then can be @@ -608,8 +592,6 @@ int setFixedFirstnameFor(String firstname, String lastname); without the need to declare a query (method) for every needed combination. Here's an example: - - Specifications for a Customer @@ -626,7 +608,6 @@ int setFixedFirstnameFor(String firstname, String lastname); }; } - public static Specification<Customer> hasSalesOfMoreThan(MontaryAmount value) { return new Specification<Customer>() { Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, @@ -639,8 +620,6 @@ int setFixedFirstnameFor(String firstname, String lastname); } - - Admittedly the amount of boilerplate leaves room for improvement (that will hopefully be reduced by Java 8 closures) but the client side becomes much nicer as you will see below. Besides that we have expressed @@ -649,16 +628,12 @@ int setFixedFirstnameFor(String firstname, String lastname); might use a Specification as follows: - - Using a simple Specification List<Customer> customers = customerRepository.findAll(isLongTermCustomer()); - - Okay, why not simply create a query for this kind of data access? You're right. Using a single Specification does not gain a lot of benefit over a plain query declaration. The power @@ -668,8 +643,6 @@ int setFixedFirstnameFor(String firstname, String lastname); Specifications helper class we provide to build expressions like this: - - Combined Specifications @@ -683,8 +656,6 @@ List<Customer> customers = customerRepository.readAll( Specification implementations and combining them with ones already existing. - -