Advertisement
Advertisement

More Related Content

Advertisement
Advertisement

Thinking Beyond ORM in JPA

  1. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Thinking Beyond ORM in JPA Patrycja Wegrzynowicz CTO Yonita, Inc. March 15, 2016 Please Stand By. This session will begin promptly at the time indicated on the agenda. Thank You.
  2. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Safe Harbor Statement The following is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle. 2
  3. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | About Me • 15+ professional experience – Still an active developer! • Author and speaker – JavaOne, Devoxx, JavaZone, others • Finalizing PhD in Computer Science • Founder and CTO of Yonita – Consulting plus automated tools for detection of bugs in software – Security, performance, databases • Twitter @yonlabs Oracle Confidential – Internal/Restricted/Highly Restricted 3
  4. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Outline • Why? – App-centric vs. data-centric • What? – Use cases and performance • How? – JPA (2.1)
  5. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Database
  6. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Database – The Mordor of Java Developers
  7. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Why? Different paradigms! • One size doesn’t fit all! • App-centric – Java code drives database design – One app accesses data – CRUD more often than complex queries • Data-centric – Database design drives Java code – Several apps access data – CRUD as often as complex queries
  8. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | What? Use Cases
  9. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | What? Performance
  10. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Legacy Systems
  11. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Legacy systems and Database-Level Abstraction • Legacy systems – It’s always worked that way! – Database was all we had! – We need to feed all those apps! • Abstraction – Views – Stored procedures – Triggers
  12. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Stored Procedures in JPA • 2.0 and before – Native queries to call stored procedures – No OUT/INOUT parameters – Database dependent CALL syntax • 2.1 – EntityManager.createStoredProcedureQuery – @NamedStoredProcedureQuery
  13. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure Result Set -- MySQL CREATE PROCEDURE GET_EMPLOYEES() BEGIN SELECT * FROM EMPLOYEES; END
  14. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); // gather the results List<Employee> list = (List<Employee>) q.getResultList();
  15. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); // gather the results List<Employee> list = (List<Employee>) q.getResultList();
  16. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); // gather the results List<Employee> list = (List<Employee>) q.getResultList();
  17. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); // gather the results, an implicit call to an execute method! List<Employee> list = (List<Employee>) q.getResultList();
  18. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure OUT Parameter -- MySQL CREATE PROCEDURE SUM_SALARIES(OUT TOTAL INT) BEGIN SELECT SUM(SALARY) INTO TOTAL FROM EMPLOYEES; END
  19. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("SUM_SALARIES"); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // execute the query... q.execute(); // ...to obtain the output value Integer total = (Integer) q.getOutputParameterValue("TOTAL");
  20. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("SUM_SALARIES"); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // execute the query... q.execute(); // ...to obtain the output value Integer total = (Integer) q.getOutputParameterValue("TOTAL");
  21. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("SUM_SALARIES"); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // execute the query... q.execute(); // ...to obtain the output value Integer total = (Integer) q.getOutputParameterValue("TOTAL");
  22. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("SUM_SALARIES"); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // execute the query... q.execute(); // ...to obtain the output value Integer total = (Integer) q.getOutputParameterValue("TOTAL");
  23. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure All in One -- MySQL CREATE PROCEDURE GET_EMPLOYEES( IN GIVEN_COUNTRY VARCHAR(255), OUT TOTAL INT ) BEGIN SELECT SUM(SALARY) INTO TOTAL FROM EMPLOYEES WHERE COUNTRY = GIVEN_COUNTRY; SELECT * FROM EMPLOYEES WHERE COUNTRY = GIVEN_COUNTRY; END
  24. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // setup the parameters q.setParameter("COUNTRY", "Poland"); // obtain the employees... List<Employee> list = (List<Employee>) q.getResultList(); // ...and the output value Integer total = (Integer) q.getOutputParameterValue("TOTAL");
  25. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // setup the parameters q.setParameter("COUNTRY", "Poland"); // obtain the employees... List<Employee> list = (List<Employee>) q.getResultList(); // ...and the output value Integer total = (Integer) q.getOutputParameterValue("TOTAL");
  26. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // setup the parameters q.setParameter("COUNTRY", "Poland"); // obtain the employees... List<Employee> list = (List<Employee>) q.getResultList(); // ...and the output value Integer total = (Integer) q.getOutputParameterValue("TOTAL");
  27. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // setup the parameters q.setParameter("COUNTRY", "Poland"); // obtain the employees... List<Employee> list = (List<Employee>) q.getResultList(); // ...and the output value Integer total = (Integer) q.getOutputParameterValue("TOTAL");
  28. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // setup the parameters q.setParameter("COUNTRY", "Poland"); // obtain the employees... List<Employee> list = (List<Employee>) q.getResultList(); // ...and the output value Integer total = (Integer) q.getOutputParameterValue("TOTAL");
  29. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES",Employee.class); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // setup the parameters q.setParameter("COUNTRY", "Poland"); // obtain the employees List<Employee> list = (List<Employee>) q.getResultList(); // do we need the execute call here? Integer total = (Integer) q.getOutputParameterValue("TOTAL");
  30. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // setup the parameters q.setParameter("COUNTRY", "Poland"); // first, an implicit call to execute List<Employee> list = (List<Employee>) q.getResultList(); // ...then, we can safely obtain the output value  Integer total = (Integer) q.getOutputParameterValue("TOTAL");
  31. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // setup the parameters q.setParameter("COUNTRY", "Poland"); // what if we reorder the lines? Integer total = (Integer) q.getOutputParameterValue("TOTAL"); List<Employee> list = (List<Employee>) q.getResultList();
  32. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // setup the parameters q.setParameter("COUNTRY", "Poland"); // what if we reorder the lines? Integer total = (Integer) q.getOutputParameterValue("TOTAL"); // an implicit call to execute List<Employee> list = (List<Employee>) q.getResultList();
  33. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // setup the parameters q.setParameter("COUNTRY", "Poland"); // execute must be called before getOutputParameterValue q.execute(); Integer total = (Integer) q.getOutputParameterValue("TOTAL"); List<Employee> list = (List<Employee>) q.getResultList();
  34. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // setup the parameters q.setParameter("COUNTRY", "Poland"); // execute must be called before getOutputParameterValue q.execute(); Integer total = (Integer) q.getOutputParameterValue("TOTAL"); // does it call execute once more? List<Employee> list = (List<Employee>) q.getResultList();
  35. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // setup the parameters q.setParameter("COUNTRY", "Poland"); // execute must be called before getOutputParameterValue q.execute(); Integer total = (Integer) q.getOutputParameterValue("TOTAL"); // an implicit call to execute only if not executed yet! List<Employee> list = (List<Employee>) q.getResultList();
  36. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); // what about the order here? q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // setup the parameters q.setParameter("COUNTRY", "Poland"); // execute and retrieve the results q.execute(); Integer total = (Integer) q.getOutputParameterValue("TOTAL"); List<Employee> list = (List<Employee>) q.getResultList();
  37. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); // what if we switch the lines? q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN); // setup the parameters q.setParameter("COUNTRY", "Poland"); // execute and retrieve the results q.execute(); Integer total = (Integer) q.getOutputParameterValue("TOTAL"); List<Employee> list = (List<Employee>) q.getResultList();
  38. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); // what about the order here? q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT); // setup the parameters q.setParameter("COUNTRY", "Poland"); // execute and retrieve the results q.execute(); Integer total = (Integer) q.getOutputParameterValue("TOTAL"); List<Employee> list = (List<Employee>) q.getResultList();
  39. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); // what about the order of the positional parameters? q.registerStoredProcedureParameter(2, Integer.class, ParameterMode.OUT); q.registerStoredProcedureParameter(1, String.class, ParameterMode.IN); // setup the parameters q.setParameter("COUNTRY", "Poland"); // execute and retrieve the results q.execute(); Integer total = (Integer) q.getOutputParameterValue("TOTAL"); List<Employee> list = (List<Employee>) q.getResultList();
  40. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); // what about the order of the positional parameters? q.registerStoredProcedureParameter(2, Integer.class, ParameterMode.OUT); q.registerStoredProcedureParameter(1, String.class, ParameterMode.IN); // setup the parameters q.setParameter("COUNTRY", "Poland"); // execute and retrieve the results q.execute(); Integer total = (Integer) q.getOutputParameterValue("TOTAL"); List<Employee> list = (List<Employee>) q.getResultList();
  41. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure Annotation @NamedStoredProcedureQuery { name = "getEmployees", procedureName = "GET_EMPLOYEES", resultClasses = Employee.class, parameters = { @StoredProcedureParameter(name="COUNTRY", mode=ParameterMode.IN, type=String.class), @StoredProcedureParameter(name="TOTAL", mode=ParameterMode.OUT, type=Integer.class) } } @Entity public class Employee { // … }
  42. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createNamedStoredProcedureQuery("getEmployees"); // setup the parameters q.setParameter("COUNTRY", "Poland"); // first, an implicit call to execute List<Employee> list = (List<Employee>) q.getResultList(); // ...then, we can safely obtain the output value  Integer total = (Integer) q.getOutputParameterValue("TOTAL");
  43. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createNamedStoredProcedureQuery("getEmployees"); // setup the parameters q.setParameter("COUNTRY", "Poland"); // first, an implicit call to execute List<Employee> list = (List<Employee>) q.getResultList(); // ...then, we can safely obtain the output value  Integer total = (Integer) q.getOutputParameterValue("TOTAL");
  44. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createNamedStoredProcedureQuery("getEmployees"); // setup the parameters q.setParameter("COUNTRY", "Poland"); // first, an implicit call to execute List<Employee> list = (List<Employee>) q.getResultList(); // ...then, we can safely obtain the output value  Integer total = (Integer) q.getOutputParameterValue("TOTAL");
  45. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createNamedStoredProcedureQuery("getEmployees"); // no calls to registerStoredProcedureParameter // setup the parameters q.setParameter("COUNTRY", "Poland"); // first, an implicit call to execute List<Employee> list = (List<Employee>) q.getResultList(); // ...then, we can safely obtain the output value  Integer total = (Integer) q.getOutputParameterValue("TOTAL");
  46. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure -- PostgreSQL CREATE OR REPLACE FUNCTION GET_EMPLOYEES( IN GIVEN_COUNTRY VARCHAR(255), OUT TOTAL INT) RETURNS REFCURSOR AS $BODY$ DECLARE EMPS REFCURSOR; BEGIN OPEN EMPS FOR SELECT * FROM EMPLOYEE WHERE COUNTRY = GIVEN_COUNTRY; RETURN EMPS; END; $BODY$ LANGUAGE plpgsql
  47. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure -- PostgreSQL CREATE OR REPLACE FUNCTION GET_EMPLOYEES( IN GIVEN_COUNTRY VARCHAR(255), OUT TOTAL INT) RETURNS REFCURSOR AS $BODY$ DECLARE EMPS REFCURSOR; BEGIN OPEN EMPS FOR SELECT * FROM EMPLOYEE WHERE COUNTRY = GIVEN_COUNTRY; RETURN EMPS; END; $BODY$ LANGUAGE plpgsql
  48. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class); q.registerStoredProcedureParameter(1, void.class, ParameterMode.REF_CURSOR); q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN); // setup the parameters q.setParameter("COUNTRY", "Poland"); // an implicit call to execute List<Employee> list = (List<Employee>) q.getResultList();
  49. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure Annotation @NamedStoredProcedureQuery( name = "getEmployees", procedureName = "GET_EMPLOYEES", resultClasses = Employee.class, parameters = { @StoredProcedureParameter(mode=ParameterMode.REF_CURSOR, type=void.class), @StoredProcedureParameter(name="COUNTRY", mode=ParameterMode.IN, type=String.class) } ) @Entity public class Employee { // … }
  50. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createNamedStoredProcedureQuery(”getEmployees”); // setup the parameters q.setParameter("COUNTRY", "Poland"); // an implicit call to execute List<Employee> list = (List<Employee>) q.getResultList();
  51. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure Annotation @NamedStoredProcedureQuery( name = "getEmployees", procedureName = "GET_EMPLOYEES", resultClasses = Employee.class, parameters = { @StoredProcedureParameter(mode=ParameterMode.REF_CURSOR, type=void.class), @StoredProcedureParameter(name="COUNTRY", mode=ParameterMode.IN, type=String.class) } ) @Entity public class Employee { // … }
  52. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createNamedStoredProcedureQuery("getEmployees"); // setup the parameters q.setParameter(2, "Poland"); // obtain the result List<Employee> list = (List<Employee>) q.getResultList();
  53. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Example: Stored Procedure EntityManager API // create and setup a stored procedure query StoredProcedureQuery q = em.createNamedStoredProcedureQuery("getEmployees"); // setup the parameters q.setParameter(2, "Poland"); // obtain the result List<Employee> list = (List<Employee>) q.getResultList();
  54. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Stored Procedures in JPA 2.1 Wrap-up • Annotation – @NamedStoredProcedureQuery • EntityManager API – createStoredProcedureQuery – registerStoredProcedureParameter • Use cases – Existing database – Abstraction on database level (e.g., for several applications) • Still differences between databases! – Much smaller though
  55. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Reporting
  56. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Reporting Anti-Patterns • Direct usage of an object-oriented domain model • Too much data loaded • Heavy processing on the Java side
  57. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Reporting Anti-Patterns Example
  58. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Reporting Anti-Patterns Employee Entity @Entity public class Employee { @Id @GeneratedValue private Long id; private String firstName; private String lastName; private BigDecimal salary; @OneToOne @JoinColumn(name = "address_id") private Address address; @Temporal(TemporalType.DATE) private Date startDate; @Temporal(TemporalType.DATE) private Date endDate; @ManyToOne @JoinColumn(name = "manager_id") private Employee manager; // … }
  59. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Sum of Salaries By Country Select All (1) TypedQuery<Employee> query = em.createQuery( "SELECT e FROM Employee e", Employee.class); List<Employee> list = query.getResultList(); // calculate sum of salaries by country // map: country->sum Map<String, BigDecimal> results = new HashMap<>(); for (Employee e : list) { String country = e.getAddress().getCountry(); BigDecimal total = results.get(country); if (total == null) total = BigDecimal.ZERO; total = total.add(e.getSalary()); results.put(country, total); }
  60. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Sum of Salaries by Country Select Join Fetch (2) TypedQuery<Employee> query = em.createQuery( "SELECT e FROM Employee e JOIN FETCH e.address", Employee.class); List<Employee> list = query.getResultList(); // calculate sum of salaries by country // map: country->sum Map<String, BigDecimal> results = new HashMap<>(); for (Employee e : list) { String country = e.getAddress().getCountry(); BigDecimal total = results.get(country); if (total == null) total = BigDecimal.ZERO; total = total.add(e.getSalary()); results.put(country, total); }
  61. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Reporting Anti-Patterns Projection (3) Query query = em.createQuery( "SELECT e.salary, e.address.country FROM Employee e"); List<Object[]> list = (List<Object[]>) query.getResultList(); // calculate sum of salaries by country // map: country->sum Map<String, BigDecimal> results = new HashMap<>(); for (Object[] e : list) { String country = (String) e[1]; BigDecimal total = results.get(country); if (total == null) total = BigDecimal.ZERO; total = total.add((BigDecimal) e[0]); results.put(country, total); }
  62. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Reporting Anti-Patterns Aggregation JPQL (4) Query query = em.createQuery( "SELECT SUM(e.salary), e.address.country FROM Employee e GROUP BY e.address.country"); List<Object[]> list = (List<Object[]>) query.getResultList(); // already calculated!
  63. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Reporting Anti-Patterns Aggregation SQL (5) Query query = em.createNativeQuery( "SELECT SUM(e.salary), a.country FROM employee e JOIN address a ON e.address_id = a.id GROUP BY a.country"); List<Object[]> list = (List<Object[]>) query.getResultList(); // already calculated!
  64. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Comparison 1-5 100 000 employees, EclipseLink MySQL PostgreSQL Select all (1+N) (1) 25704ms 18120ms Select join fetch (2) Projection (3) Aggregation JPQL (4) Aggregation SQL (5)
  65. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Comparison 1-5 100 000 employees, EclipseLink MySQL PostgreSQL Select all (1+N) (1) 25704ms 18120ms Select join fetch (2) 6211ms 3954ms Projection (3) Aggregation JPQL (4) Aggregation SQL (5)
  66. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Comparison 1-5 100 000 employees, EclipseLink MySQL PostgreSQL Select all (1+N) (1) 25704ms 18120ms Select join fetch (2) 6211ms 3954ms Projection (3) 533ms 569ms Aggregation JPQL (4) Aggregation SQL (5)
  67. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Comparison 1-5 100 000 employees, EclipseLink MySQL PostgreSQL Select all (1+N) (1) 25704ms 18120ms Select join fetch (2) 6211ms 3954ms Projection (3) 533ms 569ms Aggregation JPQL (4) 410ms 380ms Aggregation SQL (5) 380ms 409ms
  68. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | MySQL vs. PostgreSQL 68 25704 6211 533 410 380 18120 3954 569 380 4090 5000 10000 15000 20000 25000 30000 Select all (1+N) (1) Select join fetch (2) Projection (3) Aggregation JPQL (4) Aggregation SQL (5) MySQL PostgreSQL
  69. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Projection JPQL -> Value Object Query query = em.createQuery( "SELECT new com.yonita.jpa.vo.EmployeeVO(e.salary, e.address.country) FROM Employee e"); // The list of value objects List<EmployeeVO> list = (List<EmployeeVO>) query.getResultList();
  70. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Projection JPQL -> Value Object Query query = em.createQuery( "SELECT new com.yonita.jpa.CountryStatVO( sum(e.salary), e.address.country) FROM Employee e GROUP BY e.address.country"); // The list of value objects List<CountryStatVO> list = (List<CountryStatVO>) query.getResultList();
  71. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Projection SQL -> Value Object @SqlResultSetMapping( name = "countryStatVO", classes = { @ConstructorResult( targetClass = CountryStatVO.class, columns = { @ColumnResult(name = "ssum", type = BigDecimal.class), @ColumnResult(name = "country", type = String.class) }) } )
  72. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Projection SQL -> Value Object Query query = em.createNativeQuery("countryStatVO"); // The list of value objects List<CountryStatVO> list = (List<CountryStatVO>) query.getResultList();
  73. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Projection Wrap-up • JPA 2.0 – Only JPQL query to directly produce a value object! • JPA 2.1 – JPQL and native queries to directly produce a value object! • Managed entities – Sync with database – L1/L2 cache • Use cases for Direct Value Object – Reporting, statistics, history – Read-only data, GUI data • Performance – No need for managed objects – Rich (or fat) managed objects – Subset of attributes required – Gain speed – Offload an app server
  74. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Aggregation Wrap-up • JPA 2.0 – Selected aggregation functions: COUNT, SUM, AVG, MIN, MAX • JPA 2.1 – All function as supported by a database – Call any database function with new FUNCTION keyword • Database-specific aggregate functions – MS SQL: STDEV, STDEVP, VAR, VARP,… – MySQL: BIT_AND, BIT_OR, BIT_XOR,… – Oracle: MEDIAN, PERCENTILE,… – More… • Use cases – Reporting, statistics – Performance • Gain speed • Offload an app server to a database!
  75. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Complex Queries
  76. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | JPQL vs. SQL • Column/table visibility – JPA 2.0/2.1: Only mapped columns and tables • Operations on sets – UNION, INTERSECT, EXCEPT – JPA 2.0/2.1: No support • Nested fetch joins – JPA 2.0: No support – JPA 2.1: entity graphs for different fetching strategies • ON – JPA 2.0: No support – JPA 2.1: Only on “connected entities”
  77. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | JPQL vs. SQL • Database functions – Aggregate functions – Conversion functions – Extraction functions – Manipulation functions – Functions, functions, functions… – JPA 2.0: Selected functions – JPA 2.1: All functions
  78. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Helper Functions JPA 2.1 • String functions: – CONCAT, SUBSTRING, TRIM, LOWER, UPPER, LENGTH, LOCATE • Arithmetic functions: – ABS, SQRT, MOD, SIZE, INDEX • Date/time functions: – CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP • Aggregate functions: – COUNT, SUM, MIN, MAX, AVG • Invocation of predefined or user-defined functions: – FUNCTION(function_name {, function_args}*)
  79. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Helper Functions JPA 2.1 • Invocation of predefined or user-defined functions: – FUNCTION(function_name {, function_args}*) – SELECT c FROM Customer c WHERE FUNCTION(‘hasGoodCredit’, c.balance, c.creditLimit)
  80. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | JPA 2.1
  81. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Wrap-up • JPA 2.1 – Stored procedures support – Projections • Direct value object for native queries – Richer JPQL
  82. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Wrap-up • JPA 2.1 – Stored procedures support – Projections • Direct value object for native queries – Richer JPQL • Performance
  83. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Wrap-up • JPA 2.1 – Stored procedures support – Projections • Direct value object for native queries – Richer JPQL • Performance – Don’t load if you don’t need
  84. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Wrap-up • JPA 2.1 – Stored procedures support – Projections • Direct value object for native queries – Richer JPQL • Performance – Don’t load if you don’t need – Don’t execute many small queries if you can execute one big query
  85. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Wrap-up • JPA 2.1 – Stored procedures support – Projections • Direct value object for native queries – Richer JPQL • Performance – Don’t load if you don’t need – Don’t execute many small queries if you can execute one big query – Don’t calculate if a database can
  86. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | A fool with a tool is still a fool!
  87. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Continuous Learning Paradigm 87
  88. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Q+A
  89. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Keep Learning with Training from Oracle University 89 • Hands-on training delivered in-class or online by tenured instructors around the world • New subscription-based learning services to give you any-time access to training • Certification programs to validate your skills education.oracle.com
  90. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | 90
  91. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | 91
  92. Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | 92
Advertisement