© Copyright 2018 Pivotal Software, Inc. All rights Reserved.
May 2019
Spring Data JPA
0-100 in 60 minutes
“for they know not what they do” 

(Lk 23:34)
Spring Data JPA builds on JPA
JPA Basics
JPA Basics
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long id;
@Version
Long version;
String firstName;
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
Address address;
@ManyToMany(cascade = CascadeType.ALL)
Set<Hobby> hobbies = new HashSet<>();
Gender gender;
}
JPA Basics
Person p = createPerson();
em.persist(p);
// select count(*) from Person
Person reloaded = em.find(Person.class, p.getId());
// select count(*) from Person
Person reloadedAgain = em
.createQuery("SELECT p FROM Person p " +
"WHERE p.id = :id", Person.class)
.setParameter("id", p.getId())
.getSingleResult();
// select count(*) from Person
JPA Basics
@Transactional
public class PersonService {
@Autowired
EntityManager em;
public void setName(Long id, String name) {
em.find(Person.class, id).setFirstName(name);
}
public Person loadPerson(Long id) {
return em.find(Person.class, id);
}
}
JPA Basics
Person person = personService.loadPerson(id);
person.getAddress();
person.getHobbies().forEach(System.out::println);
What does
Spring Data JPA do for you?
Spring Data JPA
CRUD
Spring Data JPA
CRUD
interface PersonRepository
extends JpaRepository<Person, Long> {}
CRUD
@Autowired
PersonRepository persons;
// …
Person p = persons.save(createPerson());
persons.findById(id);
persons.findAll();
persons.deleteAll();
Query Derivation
Spring Data JPA
Derived Queries
interface PersonRepository
extends JpaRepository<Person, Long> {
List<Person> findByFirstName(String firstName);
boolean existsByAddress_CityContainsIgnoreCase(
String name);
}
Derived Queries
persons.findByFirstName("Jens");
persons.existsByAddress_CityContainsIgnoreCase(“aREST");
Annotated Queries
Spring Data JPA
Annotated Queries
interface PersonRepository
extends JpaRepository<Person, Long> {
// …
@Query("SELECT CONCAT( p.firstName, 'n', a.zipCode, ' ', a.city) " +
"FROM Person p " +
"JOIN p.address AS a " +
"WHERE a.city LIKE :#{#city == null || #city.isEmpty() ?
'%' : #city}")
List<String> addressListByNullableCity(String city);
}
Pagination
Spring Data JPA
Derived Queries
interface PersonRepository
extends JpaRepository<Person, Long> {
List<Person> findByFirstName(String firstName);
// …
}
Derived Queries
interface PersonRepository
extends JpaRepository<Person, Long> {
Page<Person> findByFirstName(String firstName, Pageable page);
// …
}
Derived Queries
interface PersonRepository
extends JpaRepository<Person, Long> {
Slice<Person> findByFirstName(String firstName, Pageable page);
// …
}
Projections
Spring Data JPA
Derived Queries
interface PersonRepository
extends JpaRepository<Person, Long> {
List<Person> findByFirstName(String firstName);
// …
}
Derived Queries
interface PersonRepository
extends JpaRepository<Person, Long> {
List<SimplePerson> findSimplyByFirstName(String firstName);
// …
}
Derived Queries
public interface SimplePerson {
String getFirstName();
Gender getGender();
@Value("#{target.address.city + ' in ' + target.address.state}")
String getAddress();
}
Conversions
Spring Data JPA
Query By Example
Spring Data JPA
Query by Example
Person pattern = new Person(
null,
new Address(null, null, "germany"),
Gender.MALE,
null
);
Example<Person> strict = Example.of(pattern);
persons.findAll(strict);
Query by Example
Example<Person> lenient = Example.of(
pattern,
ExampleMatcher.matchingAll().withIgnoreCase()
);
persons.findAll(lenient);
Specifications
Spring Data JPA
Specifications
interface PersonRepository
extends JpaRepository<Person, Long>, JpaSpecificationExecutor<Person>
{
// …
}
Specifications
persons.findAll(notFrom("new"))
// …
Specification<Person> notFrom(String cityPart) {
return (Specification<Person>)
(Root<Person> root, CriteriaQuery<?> cq, CriteriaBuilder cb) ->
cb.not(
cb.like(
root.get("address").get("city"),
"%" + cityPart + "%"
)
);
}
Querydsl Support
Spring Data JPA
Specifications
interface PersonRepository
extends JpaRepository<Person, Long>, QueryDslPredicateExecutor
{
// …
}
Specifications
persons.findAll(notFrom("new"))
// …
BooleanExpression notFrom(String cityPart) {
return QPerson.person
.address.city
.containsIgnoreCase(cityPart).not();
}
What is Spring Data JDBC?
Alternativ to Spring Data JPA
What if something breaks?
Spring Data JPA or JPA
References
! Github: https://github.com/spring-projects/spring-data-jpa
! Reference: https://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/
! Official examples: https://github.com/spring-projects/spring-data-examples/tree/
master/jpa
! Examples for these slides: https://github.com/schauder/talk-spring-data-jpa-0-100/
tree/master/example
! Article about specifications and Querydsl with Spring Data JPA: https://spring.io/blog/
2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/
Jens Schauder
! Spring Data JPA
! Spring Data JDBC
! jschauder@pivotal.io
! Father
! Plays (Roleplaying) Games
! Fitness & Sports
! @jensschauder
! blog.schauderhaft.de
Attribution
! https://upload.wikimedia.org/wikipedia/commons/8/8d/
Shimano_three_gear_hub_lever.jpg (CC-BY-SA 3.0)

Spring Data JPA from 0-100 in 60 minutes