26
Spring Data JPA https://docs.spring.io/spring-data/jpa/docs/current/reference/html/ CAS Java Microservice Development Simon Martinelli, [email protected], v2018.11

Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

Spring Data JPA

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/

CAS Java Microservice Development

Simon Martinelli, [email protected], v2018.11

Page 2: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

Spring Data JPA Stack

JDBC DataSource

HikariCP (Connection Pool)

Hibernate

JPA

Page 3: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

Repositories

3

Page 4: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

Repository

4

<<Interface>>

JpaRepository<T, ID>

<<Interface>>

PagingAndSortingRepository<T, ID>

<<Interface>>

QueryByExampleExecutor<T, ID>

<<Interface>>

CrudRepository<T, ID>

<<Interface>>

Repository<T, ID>

SimpleJpaRepository<T, ID>

<<Interface>>

JpaSpecificationExecutor<T>

This is the default implementation

Page 5: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

Custom Repository

5

<<Interface>>

JpaRepository<T, ID>

<<Interface>>

CustomEmployeeRepository

CustomRepositoryImpl<<Interface>>

EmployeeRepository<Employee, Integer>

Impl is a mandatory naming conventioin

Page 6: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

▶ Transactions are set to @Transactional(readOnly = true) on class level

▶ Transactional are all modifying methods:

▶ delete*

▶ save*

▶ flush()

▶ Caution:

This has a different semantic than JPA that doesn’t know a save method

Transaction Handling

6

Page 7: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

public interface UserRepository extends Repository<User, Long> {

List<User> findByEmailAddressAndLastname(String emailAddress, String lastname);

}

results in

select u from User u where u.emailAddress = ?1 and u.lastname = ?2

Spring Data JPA does a property check and traverses nested properties

Query Generation

7

Page 8: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

▶ find* can have many return types

▶ Void, Primitives, Wrapper types, T, Iterator<T>, Collection<T>, List<T>,

Optional<T>, Stream<T>, Future<T>, CompletableFuture<T>,

ListenableFuture, Slice, Page<T>, GeoResult<T>, GeoResults<T>,

GeoPage<T>, Mono<T>, Flux<T>, Single<T>, Maybe<T>, Flowable<T>

▶ Repository CRUD methods that return an individual aggregate instance use

Java 8 Optional to indicate the potential absence of a value

Query Return Types

8

Page 9: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

▶ We can define our own queries using @Query annotation

@Query("select e from Employee e order by e.name")

List<Employee> findAllEmployeesOrderByName();

@Query

9

Page 10: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

▶ Using the constructor expression to create DTOs

@Query("select new jmdhs18.hr.model.DepartmentDTO(d.name, count(e)) " +

"from Department d join d.employees e group by d.name")

List<DepartmentDTO> findAllDepartmentDTO();

public class DepartmentDTO {

private final String name;

private final Long numberOfEmployees;

public DepartmentDTO(String name, Long numberOfEmployees) {

this.name = name;

this.numberOfEmployees = numberOfEmployees;

}

}

DTO-based Projection

10

Page 11: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

▶ Use Interfaces

@Query("select d.name from Department d join d.employees e group by d.name")

List<DepartmentNames> findAllDepartmentNames();

public interface DepartmentNames {

String getName();

}

Interface-based Projection

11

Page 12: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

▶ SQL can be used by defining the Query as nativeQuery:

@Query("select d.* from Department d", nativeQuery = true)

List<Department> findAllDepartmentNames();

Using SQL

12

Page 13: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

▶ Parameters are positional by default

@Query("select u from User u where u.firstname = ?1 or u.lastname = ?2")

User findByLastnameOrFirstname(@Param("lastname") String lastname,

@Param("firstname") String firstname);

▶ But you can use named parameters too

@Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")

User findByLastnameOrFirstname(String lastname, String firstname);

Parameters

13

Page 14: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

public interface PagingAndSortingRepository<T, ID

extends Serializable> extends CrudRepository<T, ID> {

Iterable<T> findAll(Sort sort);

Page<T> findAll(Pageable pageable);

}

Page<User> users = repository.findAll(new PageRequest(1, 20, Sort.by("name"));

Paging and Sorting

14

Page 15: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

▶ By extending JpaSpecificationExecutor we get find* methods that take a

Specification as a parameter.

▶ The Specification method toPredicate provides all objects to create a Criteria API

Predicate

List<Employee> list = employeeRepository.findAll(new Specification() {

@Override

public Predicate toPredicate(Root employee, CriteriaQuery query,

CriteriaBuilder criteriaBuilder) {

return criteriaBuilder.equal(employee.get(Employee_.name), name);

}

});

Specifications

15

Page 16: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

▶ You can use Insert, Update and Delete but you have to tell Spring Data that

these are modifying queries

@Modifying

@Query("update User u set u.firstname = ?1 where u.lastname = ?2")

int setFixedFirstnameFor(String firstname, String lastname);

Modifying Queries

16

Page 17: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

Database Management

17

Page 18: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

▶ spring.jpa.generate-ddl

▶ Switches the feature on and off and is vendor independent

▶ spring.jpa.hibernate.ddl-auto

▶ Hibernate feature that controls the behavior in a more fine-grained way

▶ Values are none, validate, update, create, and create-drop

JPA and Hibernate DDL Generation

18

Page 19: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

▶ Turn initialization on

▶ spring.datasource.initialization-mode=always

▶ SQL Files

▶ schema.sql → Creates the schema

▶ data.sql → Loads data

▶ Can be database platform dependent

▶ schema-${platform}.sql

▶ data-${platform}.sql

▶ Can also be mixed by omitting schema.sql and let Hibernate create the schema

Database Initialization

19

Page 20: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

▶ Spring Boot supports Flyway and Liquibase

▶ Spring Boot autoconfigures Flyway and Liquibase when on the classpath

▶ To use Flyway https://flywaydb.org/

1. Add org.flywaydb:flyway-core dependency to pom.xml

2. Add migration files to classpath:db/migration

Database Migration

20

Page 21: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

Flyway Migrations

21

Page 22: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

Testing

22

Page 23: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

▶ Unit Test

▶ Check if an individual small piece of code is doing what it is supposed to do

▶ Integration Test

▶ Check if different pieces of the modules work together as a whole

▶ Maven support

▶ *Test run with Surefire Plugin

▶ Runs during test phase

▶ https://maven.apache.org/surefire/maven-surefire-plugin/

▶ *IT run Failsafe Plugin

▶ Must be configured. Usually runs in verify phase

▶ https://maven.apache.org/surefire/maven-failsafe-plugin/

Unit vs Integration Tests

23

Page 24: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

▶ Spring Boot’s auto-configuration system works well for applications but can

sometimes be a little too much for tests

▶ It often helps to load only the parts of the configuration that are required to test

a “slice” of your application

▶ For example

▶ Test that Spring MVC controllers are mapping URLs correctly, and you do not

want to involve database calls in those tests

▶ Test JPA entities, and you are not interested in the web layer when those

tests run

Spring Boot Test Slices

24

Page 25: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

▶ Use the @DataJpaTest annotation to test JPA applications

▶ By default

▶ it configures an in-memory embedded database

▶ scans for @Entity classes

▶ configures Spring Data JPA repositories

▶ Regular @Component beans are not loaded into the ApplicationContext

▶ You can use a “regular” database instead of the in-memory database

@DataJpaTest

@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)

@RunWith(SpringRunner.class)

public class CriteriaTest {

DataJpaTest

25

Page 26: Spring Data JPA - sws.bfh.ch › ~fischli › courses › info › spring › scripts › SpringDataJpa.pdf · Spring Data JPA does a property check and traverses nested properties

▶ Runs Spring Boot based tests

▶ Provides the following features

▶ Uses “standard” database

▶ Provides support for different webEnvironment modes, including the ability

to start a fully running web server listening on a defined or random port

@SpringBootTest

@RunWith(SpringRunner.class)

public class PessimisticLockIT {

SpringBootTest

26