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

Java Data Access Performance in Combination wit...

Java Data Access Performance in Combination with Vaadin and REST API

Simon Martinelli PRO

January 09, 2022

Transcript

26 slides
  1. 5

  2. 7

  3. 8 In-Memory vs Lazy Callbacks • In-Memory • Easy to

    use if you only have a handful of items • Lazy callbacks • For larger amount of data List<Customer> customers = customerRepository.findAll(); grid.setItems(customers); grid.setItems(query -> customerRepository.findAll( PageRequest.of(query.getPage(), query.getPageSize()) ).stream() );
  4. 9 The Query Object int getOffset(); int getLimit(); int getPage();

    int getPageSize(); List<QuerySortOrder> getSortOrders(); Optional<F> getFilter();
  5. 10 Paging and Sorting • List<QuerySortOrder> getSortOrders() provides the sorted

    columns with sort direction (ascending or descending) • VaadinSpringDataHelpers.toSpringDataSort() converts the Query to a Spring Data Sort object grid.setItems(query -> customerRepository.findAll(PageRequest.of(query.getPage(), query.getPageSize(), toSpringDataSort(query)) ).stream() );
  6. 11 Lazy Data View • Provide an optional CountCallback to

    improve scrollbar behavior • Take care of performance because of the additional count query! grid.setItems( query -> customerRepository.findAll( PageRequest.of(query.getPage(), query.getPageSize(), toSpringDataSort(query))).stream(), query -> (int) customerRepository.count() );
  7. 12 Item Count Estimate • If you can’t implement a

    CountCallback you can set estimates: GridLazyDataView<Employee> dataView = grid.setItems( query -> employeeRepository .findAll(PageRequest.of(query.getOffset(),query.getLimit())) .stream()); dataView.setItemCountEstimate(1000); dataView.setItemCountEstimateIncrease(500);
  8. 13 Filtering • ComboBox is filterable out of the box

    • In Grids with lazy fetching we can use the filter in the FetchCallback filter = new TextField(); filter.setValueChangeMode(ValueChangeMode.LAZY); filter.addValueChangeListener(event -> loadData(event.getValue())); private void loadData(String name) { grid.setItems( query -> customerRepository.findAllCustomersWithRevenue( PageRequest.of(query.getPage(), query.getPageSize(), toSpringDataSort(query)), name).stream() ); }
  9. 14 ConfigurableFilterDataProvider • With ConfigurableFilterDataProvider you can pass a filter

    CallbackDataProvider<CustomerInfo, String> callbackDataProvider = DataProvider.fromFilteringCallbacks( // FetchCallback query -> customerRepository.findAllCustomersWithRevenue( PageRequest.of(query.getPage(), query.getPageSize(), toSpringDataSort(query)), query.getFilter().orElse("")).stream(), // CountCallback query -> customerRepository.countAllByLastnameLikeOrFirstnameLike(query.getFilter().orElse("")) ); // Set the DataProvider ConfigurableFilterDataProvider<CustomerInfo, Void, String> dataProvider = callbackDataProvider.withConfigurableFilter(); grid.setDataProvider(dataProvider); // Use the filter filter.addValueChangeListener(event -> { dataProvider.setFilter(event.getValue()); });
  10. 15 Identity Provider • Vaadin uses equals() to identify an

    object • What if the object doesn't implement equals()? • Define an identifierGetter new CallbackDataProvider<>( query -> employeeRepository.findAll( PageRequest.of(query.getOffset(), query.getLimit())) .stream(), query -> employeeRepository.count(), Employee::getId // Identifier! );
  11. 16 Refreshing • You can refresh all or just one

    element grid.getLazyDataView().refreshAll(); grid.getLazyDataView().refreshItem(employee);
  12. 17 Hierarchical Data Provider new AbstractBackEndHierarchicalDataProvider<>() { @Override public int

    getChildCount(HierarchicalQuery<Employee, Void> query) { if (query.getParent() == null) { return employeeRepository.countBySupervisorIsNull(); } else { return employeeRepository.countBySupervisor(query.getParent()); } } @Override public boolean hasChildren(Employee employee) { return employeeRepository.countBySupervisor(employee) > 0; } @Override protected Stream<Employee> fetchChildrenFromBackEnd(HierarchicalQuery<Employee, Void> query) { if (query.getParent() == null) { return employeeRepository.findAllBySupervisorIsNull().stream(); } else { return employeeRepository.findAllBySupervisor(query.getParent()).stream(); } } };
  13. 18 Data Provider and JPA/Hibernate • JPA Entities can be

    used • BUT be aware of lazy loading and the n+1 select problem! • Consider using projection with DTOs • Java 16 Records are a great fit public record CustomerInfo(Long id, String lastname, String firstname, double revenue) { }
  14. 20 Stop Mapping Stuff in Your Middleware • Modern databases

    provide functions to return XML or JSON data • Often it’s not necessary to make a detour using objects • https://blog.jooq.org/2019/11/13/stop-mapping-stuff-in-your-middleware-use-sqls- xml-or-json-operators-instead/ • https://www.youtube.com/watch?time_continue=973&v=wTPGW1PNy_Y
  15. 21 JSON Query select json_agg(po) as orders from (select p.id,

    p.order_date, (select json_agg(oi) from (select i.id, i.quantity, pr.name as product from order_item as i join product pr on pr.id = i.product_id where i.order_id = p.id ) oi ) as items from purchase_order as p where p.customer_id = ?) po
  16. 22 JSON Result [ { "id": 6232, "order_date": "2021-05-07", "items":

    [ { "id": 32446, "quantity": 7, "product": "Pencil" }, { "id": 32447, "quantity": 7, "product": "Pencil" } } ]
  17. 23 XML Query select xmlelement( name "orders", xmlagg(xmlelement(name "order", xmlattributes(p.id,

    p.order_date), xmlelement(name "items", (select xmlagg(xmlelement(name "item", xmlattributes(i.id, i.quantity, pr.name))) from order_item i join product pr on i.product_id = pr.id where i.order_id = p.id))) ) ) from purchase_order p where p.customer_id = ?
  18. 25 Conclusion • Displaying data with Vaadin is very easy

    but use lazy data providers to reduce memory size and enhance performance • Use projection with DTOs or Records instead of JPA Entities • Consider using SQL

More Decks by Simon Martinelli

Other Decks in Programming