Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A Spring Data’s Guide to Persistence

A Spring Data’s Guide to Persistence

Seconds before coding yet another lookup query, our hero is plucked off his office chair and put into this persistence spaceship where he meets his good friend Spring Data, a library aiming to ease the pain of every day data access, who has been around for more than 10 years.

Together, we’ll begin a journey—aided by a bunch of features like CRUD operations, query derivation, and SQL and NoSQL support—towards developer happiness.

Is this magic? Where is my finder method? When to use named queries? For all the answers, register to this session or stick your thumb up at start.spring.io


Christoph Strobl

September 02, 2021

More Decks by Christoph Strobl

Other Decks in Programming


  1. A Spring Data’s Guide to Persistence September 1–2, 2021 springone.io

  2. Safe Harbor Statement The following is intended to outline the

    general direction of VMware's offerings. It is intended for information purposes only and may not be incorporated into any contract. Any information regarding pre-release of VMware offerings, future updates or other planned modifications is subject to ongoing evaluation by VMware and is subject to change. This information is provided without warranty or any kind, express or implied, and is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions regarding VMware's offerings. These purchasing decisions should only be based on features currently available. The development, release, and timing of any features or functionality described for VMware's offerings in this presentation remain at the sole discretion of VMware. VMware has no obligation to update forward looking information in this presentation. 2
  3. DON‘T PANIC Douglas Adams, The Hitchhiker's Guide to the Galaxy

  4. 4 SELECT e FROM employee e WHERE e.firstName = :name

    JPA create().select().from(EMPLOYEE) .where(EMPLOYEE.FIRST_NAME).eq(name) .fetch() JOOQ db.employee.find({ first_name : name }) NoSQL SELECT * FROM employee WHERE first_name = %1 SQL everything MATCH (n:Employee) WHERE n.firstName = ’...’ query: { match: { first_name: '...' } }
  5. List<Employee> findByFirstName(String name) Spring Data JPA JDBC Redis Neo4j R2DBC

    MongoDB ArangoDB Couchbase Cosmos DB yugabyteDB Elasticsearch Apache Geode Apache Cassandra ...
  6. 42 life – data - everything

  7. 7 A Familiar & Consistent Programming Model That Resprects Store

    Specific Traits no silver bullet no magic not one API to rule them all
  8. The Basics

  9. Anatomy 9 Entity Manager Database Driver Template API Mapping Conversion

    Resource & Transaction Management native store format <> domain type eg. enum -> string Default Implementation Repository Interface List<Employee> findByFirstName(String name)
  10. Template APIs 10 class MongoTemplate implements MongoOperations { <T> List<T>

    find(Query query, Class<T> entityClass) <T> List<T> findAndRemove(Query query, Class<T> entityClass) <T> T execute(Class<?> entityClass, CollectionCallback<T> callback) query(where(“firstName”).is(...)) template.execute(Employee.class, collection -> { return collection.find(new Document("firstname", "...")) .into(new ArrayList()); }); Access to native driver commands
  11. Repositories 11 interface Repo<Employee, String> extends ...{ Repository CrudRepository findAll();

    findById(...) count(); save(...); delete(...); ... PagingAndSorting Repository findAll(Page); findAll(Sort); Proxy Default Implementation Store Specific List<Employee> findAll(); long count(); Predefined methods List<Employee> findByFirstName(String name); Derived Finder Method
  12. Derived Queries 12 List<Employee> findByFirstName(String name) Return Type Operation Keyword

    Match Against Bind Argument
  13. Paging vs Streaming 13 Page<Employee> findByFirstName(String name, Pageable page) Resource

    Allocation Per Invocation Stream<Employee> findByFirstName(String name) Continuous Scrolling
  14. Derived Fetch Queries 14 List<Employee> findEmployeeByFirstNameLikeOrderByAgeAsc(String name) read get query

    search stream Placeholder For Anything You Like matches contains lessThan startsWith greaterThan isEmpty isNull isNotNull before after ... Match Operator Sort Direction Delimiter Employee Page<Employee> Slice<Employee> Stream<Employee>
  15. Derived Count | Exists Queries 15 int countEmployeeByFirstNameLike(String name) boolean

    existsEmployeeByFirstNameLike(String name)
  16. Derived Delete Queries 16 @Modifying List<Employee> deleteEmployeeByFirstNameLike(String name) remove Some

    Stores Need a Little Help void long Interested in the Operation Result?
  17. 17 I‘d far rather be happy than right any day.

    IDE Support Runtime Support Douglas Adams, The Hitchhiker's Guide to the Galaxy
  18. Data Projections 18 List<View> findByFirstName(String name) Closed Interface Projection interface

    View2 { String getFirstName(); String getLastName(); } class View1 { String firstName; String lastName; } DTO Projection interface View3 { @Value(“#{target....}”) String getName(); } Open Interface Projection Flexible View On Your Data
  19. Query By Example 19 List<Employee> findAll(Example<Employee> probe) a Good Fit

    for Web Form Search Binding Page Stream long count Pageable Sort
  20. Auditing 2 0 class Employee { String firstName; String lastName;

    @CreatedDate Instant created; @LastModifiedDate Instant lastModified; }
  21. Reactive 21 Flux<Employee> findByFirstName(String name) a Reactive Stream of Data

    For a moment, nothing happened. Then, after a second or so, nothing continued to happen. once you forget to subscribe to the stream Douglas Adams, The Hitchhiker's Guide to the Galaxy
  22. Storage Engine Store Specific

  23. 23 class Employee { Long id; String firstName; String lastName;

    Manager manager; } class Manager { Long id; String name; List<Employee> employees } ID Name 1000 Marvin ID FIRST_N LAST_N MANAGER_ID 1 Ford Perfect 1000 table based manager employee linking by default { _id : 1000, name : Marvin, employees : [ { id : 1, firstName : Ford, lastName : Perfect } ... document store embedding by default
  24. 2 4 Would it save you a lot of time

    if I just gave up and went mad now? Actually, it’s not that bad once you got the differences. Decide on what you need. Not what you got or think to be cool. Douglas Adams, The Hitchhiker's Guide to the Galaxy
  25. 25 @Entity class Employee { @Id @GeneratedValue(...) Long id; @Column(name="FIRST_N")

    String firstName; ... } @Document class Employee { @Id Long id; @Field(name=”first_n") String firstName; ... } JPA MongoDB
  26. 26 @Document class Manager { Long id; String name; @DBRef

    List<Employee> employees } { _id : 1000, name : Marvin, employees : [ { $ref : employee, $id : 1 } ... native $dbref format MongoDB – Linking manager { _id : 1, ..., manager : 1000 } @Document class Employee { Long id; //... @DocumentReference Manager manager; } more common simple format employee
  27. 27 @Entity class Employee { Long id; //... @Embedded @AttributeOverrides({...})

    Manager manager; } JPA – Embedding ID FIRST_N LAST_N MANAGER_ID MANAGER_NAME 1 Ford Perfect 1000 Marvin
  28. Query Language Store Specific

  29. Richer / Slimmer API 2 9 Read the Documentation for

    store specific features @Procedure(”Employee.increaseSalary”) Integer increaseSalary(Integer raise); JPA Stored Procedure call GeoResults<Employee> findByOfficeLoactionNear(Point p, Distance max) List Stream MongoDB Geospatial Query
  30. Native Queries 3 0 @Query(“SELECT m, COUNT(e) FROM Manager m

    JOIN m.employees e GROUP BY e.name”) List<View> listManagerWithEmployeeCount(); JPA @Aggregation(“{ $project: { id : 1, name: 1, $size : employees } }”) List<View> listManagerWithEmployeeCount(); MongoDB
  31. Custom Implementations Store Specific

  32. Repositories 3 2 interface Repo<Employee, String> extends ...{ CrudRepository Repository

    PagingAndSorting Repository List<Employee> findAll(); long count(); findAll(); findById(...) count(); save(...); delete(...); ... findAll(Page); findAll(Sort); Default Implementation Proxy Store Specific
  33. Repository Fragments 3 3 interface Repo<Employee, String> extends ...{ List<Employee>

    findAll(); long count(); Default Implementation Proxy Repository CrudRepository PagingAndSorting Repository Fragment I Fragment II Fragment III Fragment Impl Custom Method Declaration invocation target
  34. Time is an illusion. Lunchtime doubly so. 3 4 Bad

    Performance? Slow Queries? Keep calm and log Douglas Adams, The Hitchhiker's Guide to the Galaxy
  35. Trouble Shooting 3 5 Repository Metrics Logfiles Network Stats Query

  36. Guides & Samples 3 6 spring.io/guides spring-projects/spring-data-examples

  37. #springone @SpringOne So long, and thanks for all the fish.

    Douglas Adams, The Hitchhiker's Guide to the Galaxy Noooo - Wait, there’s more...! Mapping Conversion Auditing Event Listeners Entity Callbacks Transactions Live Coding Spring Data Queries to the End of the Persistence Universe