thinking beyond orm in jpa

Post on 09-Apr-2017

185 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Thinking Beyond ORM in JPAPatrycja WegrzynowiczCTOYonita, Inc.March 15, 2016

Please Stand By. This session will begin promptly at the time indicated on the agenda. Thank You.

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Safe Harbor StatementThe 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

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

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)

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Database

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Database – The Mordor of Java Developers

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

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

What? Use Cases

Legacy systemsReportingComplex queriesBulk operations

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

What? Performance

SpeedLatencyThroughput

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Legacy Systems

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

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

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureResult Set-- MySQLCREATE PROCEDURE GET_EMPLOYEES()BEGIN

SELECT * FROM EMPLOYEES;END

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class);

// gather the resultsList<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class);

// gather the resultsList<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class);

// gather the resultsList<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class);

// gather the results, an implicit call to an execute method!List<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureOUT Parameter-- MySQLCREATE PROCEDURE SUM_SALARIES(OUT TOTAL INT)BEGIN

SELECT SUM(SALARY) INTO TOTALFROM EMPLOYEES;

END

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("SUM_SALARIES");q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT);

// execute the query...q.execute();

// ...to obtain the output valueInteger total = (Integer) q.getOutputParameterValue("TOTAL");

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("SUM_SALARIES");q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT);

// execute the query...q.execute();

// ...to obtain the output valueInteger total = (Integer) q.getOutputParameterValue("TOTAL");

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("SUM_SALARIES");q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT);

// execute the query...q.execute();

// ...to obtain the output valueInteger total = (Integer) q.getOutputParameterValue("TOTAL");

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("SUM_SALARIES");q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT);

// execute the query...q.execute();

// ...to obtain the output valueInteger total = (Integer) q.getOutputParameterValue("TOTAL");

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureAll in One-- MySQLCREATE PROCEDURE GET_EMPLOYEES(

IN GIVEN_COUNTRY VARCHAR(255), OUT TOTAL INT

)BEGIN

SELECT SUM(SALARY) INTO TOTALFROM EMPLOYEESWHERE COUNTRY = GIVEN_COUNTRY; SELECT *FROM EMPLOYEESWHERE COUNTRY = GIVEN_COUNTRY;

END

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class);q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN);q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT);

// setup the parametersq.setParameter("COUNTRY", "Poland");

// obtain the employees...List<Employee> list = (List<Employee>) q.getResultList();

// ...and the output valueInteger total = (Integer) q.getOutputParameterValue("TOTAL");

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class);q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN);q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT);

// setup the parametersq.setParameter("COUNTRY", "Poland");

// obtain the employees...List<Employee> list = (List<Employee>) q.getResultList();

// ...and the output valueInteger total = (Integer) q.getOutputParameterValue("TOTAL");

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class);q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN);q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT);

// setup the parametersq.setParameter("COUNTRY", "Poland");

// obtain the employees...List<Employee> list = (List<Employee>) q.getResultList();

// ...and the output valueInteger total = (Integer) q.getOutputParameterValue("TOTAL");

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class);q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN);q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT);

// setup the parametersq.setParameter("COUNTRY", "Poland");

// obtain the employees...List<Employee> list = (List<Employee>) q.getResultList();

// ...and the output valueInteger total = (Integer) q.getOutputParameterValue("TOTAL");

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class);q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN);q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT);

// setup the parametersq.setParameter("COUNTRY", "Poland");

// obtain the employees...List<Employee> list = (List<Employee>) q.getResultList();

// ...and the output valueInteger total = (Integer) q.getOutputParameterValue("TOTAL");

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES",Employee.class); q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT);

// setup the parametersq.setParameter("COUNTRY", "Poland");

// obtain the employeesList<Employee> list = (List<Employee>) q.getResultList();

// do we need the execute call here?Integer total = (Integer) q.getOutputParameterValue("TOTAL");

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class);q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN);q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT);

// setup the parametersq.setParameter("COUNTRY", "Poland");

// first, an implicit call to executeList<Employee> list = (List<Employee>) q.getResultList();

// ...then, we can safely obtain the output value Integer total = (Integer) q.getOutputParameterValue("TOTAL");

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class);q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN);q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT);

// setup the parametersq.setParameter("COUNTRY", "Poland");

// what if we reorder the lines?Integer total = (Integer) q.getOutputParameterValue("TOTAL");List<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class);q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN);q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT);

// setup the parametersq.setParameter("COUNTRY", "Poland");

// what if we reorder the lines?Integer total = (Integer) q.getOutputParameterValue("TOTAL");

// an implicit call to executeList<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryq = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class);q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN);q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT);

// setup the parametersq.setParameter("COUNTRY", "Poland");

// execute must be called before getOutputParameterValueq.execute();

Integer total = (Integer) q.getOutputParameterValue("TOTAL");List<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryq = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class);q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN);q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT);

// setup the parametersq.setParameter("COUNTRY", "Poland");

// execute must be called before getOutputParameterValueq.execute();

Integer total = (Integer) q.getOutputParameterValue("TOTAL");// does it call execute once more?List<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryq = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class);q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN);q.registerStoredProcedureParameter("TOTAL", Integer.class, ParameterMode.OUT);

// setup the parametersq.setParameter("COUNTRY", "Poland");

// execute must be called before getOutputParameterValueq.execute();

Integer total = (Integer) q.getOutputParameterValue("TOTAL");// an implicit call to execute only if not executed yet!List<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryq = 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 parametersq.setParameter("COUNTRY", "Poland");

// execute and retrieve the resultsq.execute();Integer total = (Integer) q.getOutputParameterValue("TOTAL");List<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryq = 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 parametersq.setParameter("COUNTRY", "Poland");

// execute and retrieve the resultsq.execute();Integer total = (Integer) q.getOutputParameterValue("TOTAL");List<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryq = 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 parametersq.setParameter("COUNTRY", "Poland");

// execute and retrieve the resultsq.execute();Integer total = (Integer) q.getOutputParameterValue("TOTAL");List<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryq = 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 parametersq.setParameter("COUNTRY", "Poland");

// execute and retrieve the resultsq.execute();Integer total = (Integer) q.getOutputParameterValue("TOTAL");List<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryq = 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 parametersq.setParameter("COUNTRY", "Poland");

// execute and retrieve the resultsq.execute();Integer total = (Integer) q.getOutputParameterValue("TOTAL");List<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureAnnotation@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) }}@Entitypublic class Employee { // … }

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createNamedStoredProcedureQuery("getEmployees");

// setup the parametersq.setParameter("COUNTRY", "Poland");

// first, an implicit call to executeList<Employee> list = (List<Employee>) q.getResultList();

// ...then, we can safely obtain the output value Integer total = (Integer) q.getOutputParameterValue("TOTAL");

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createNamedStoredProcedureQuery("getEmployees");

// setup the parametersq.setParameter("COUNTRY", "Poland");

// first, an implicit call to executeList<Employee> list = (List<Employee>) q.getResultList();

// ...then, we can safely obtain the output value Integer total = (Integer) q.getOutputParameterValue("TOTAL");

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createNamedStoredProcedureQuery("getEmployees");

// setup the parametersq.setParameter("COUNTRY", "Poland");

// first, an implicit call to executeList<Employee> list = (List<Employee>) q.getResultList();

// ...then, we can safely obtain the output value Integer total = (Integer) q.getOutputParameterValue("TOTAL");

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createNamedStoredProcedureQuery("getEmployees");// no calls to registerStoredProcedureParameter// setup the parametersq.setParameter("COUNTRY", "Poland");

// first, an implicit call to executeList<Employee> list = (List<Employee>) q.getResultList();

// ...then, we can safely obtain the output value Integer total = (Integer) q.getOutputParameterValue("TOTAL");

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored Procedure-- PostgreSQLCREATE 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

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored Procedure-- PostgreSQLCREATE 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

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createStoredProcedureQuery("GET_EMPLOYEES", Employee.class);q.registerStoredProcedureParameter(1, void.class, ParameterMode.REF_CURSOR);q.registerStoredProcedureParameter("COUNTRY", String.class, ParameterMode.IN);

// setup the parametersq.setParameter("COUNTRY", "Poland");

// an implicit call to executeList<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureAnnotation@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) })@Entitypublic class Employee { // … }

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createNamedStoredProcedureQuery(”getEmployees”);

// setup the parametersq.setParameter("COUNTRY", "Poland");

// an implicit call to executeList<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureAnnotation@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) })@Entitypublic class Employee { // … }

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createNamedStoredProcedureQuery("getEmployees");

// setup the parametersq.setParameter(2, "Poland");

// obtain the resultList<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Example: Stored ProcedureEntityManager API// create and setup a stored procedure queryStoredProcedureQuery q = em.createNamedStoredProcedureQuery("getEmployees");

// setup the parametersq.setParameter(2, "Poland");

// obtain the resultList<Employee> list = (List<Employee>) q.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Stored Procedures in JPA 2.1Wrap-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

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Reporting

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

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Reporting Anti-PatternsExample

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Reporting Anti-PatternsEmployee 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; // …}

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Sum of Salaries By CountrySelect 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->sumMap<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);}

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Sum of Salaries by CountrySelect 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->sumMap<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);}

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Reporting Anti-PatternsProjection (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->sumMap<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);}

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Reporting Anti-PatternsAggregation 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!

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Reporting Anti-PatternsAggregation 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!

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Comparison 1-5100 000 employees, EclipseLink

MySQL PostgreSQLSelect all (1+N) (1) 25704ms 18120msSelect join fetch (2)Projection (3)Aggregation JPQL (4)Aggregation SQL (5)

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Comparison 1-5100 000 employees, EclipseLink

MySQL PostgreSQLSelect all (1+N) (1) 25704ms 18120msSelect join fetch (2) 6211ms 3954msProjection (3)Aggregation JPQL (4)Aggregation SQL (5)

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Comparison 1-5100 000 employees, EclipseLink

MySQL PostgreSQLSelect all (1+N) (1) 25704ms 18120msSelect join fetch (2) 6211ms 3954msProjection (3) 533ms 569msAggregation JPQL (4)Aggregation SQL (5)

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Comparison 1-5100 000 employees, EclipseLink

MySQL PostgreSQLSelect all (1+N) (1) 25704ms 18120msSelect join fetch (2) 6211ms 3954msProjection (3) 533ms 569msAggregation JPQL (4) 410ms 380msAggregation SQL (5) 380ms 409ms

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

MySQL vs. PostgreSQL

68

Select

all (1

+N) (1)

Select

join fetch

(2)

Projection (3

)

Aggrega

tion JPQL (

4)

Aggrega

tion SQL (

5)0

50001000015000200002500030000

25704

6211533 410 380

18120

3954569 380 409 MySQL

PostgreSQL

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

ProjectionJPQL -> Value ObjectQuery query = em.createQuery( "SELECT new com.yonita.jpa.vo.EmployeeVO(e.salary, e.address.country) FROM Employee e");

// The list of value objectsList<EmployeeVO> list = (List<EmployeeVO>) query.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

ProjectionJPQL -> Value ObjectQuery 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 objectsList<CountryStatVO> list = (List<CountryStatVO>) query.getResultList();

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

ProjectionSQL -> Value Object@SqlResultSetMapping( name = "countryStatVO", classes = { @ConstructorResult( targetClass = CountryStatVO.class, columns = { @ColumnResult(name = "ssum", type = BigDecimal.class), @ColumnResult(name = "country", type = String.class) }) } )

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

ProjectionSQL -> Value ObjectQuery query = em.createNativeQuery("countryStatVO");

// The list of value objectsList<CountryStatVO> list = (List<CountryStatVO>) query.getResultList();

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

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

AggregationWrap-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!

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Complex Queries

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”

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

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}*)

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 cWHERE FUNCTION(‘hasGoodCredit’, c.balance, c.creditLimit)

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

JPA 2.1

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

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

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

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

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

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

A fool with a tool is still a fool!

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Continuous Learning Paradigm

87

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Q+A

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

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |

Thank You for Joining Us TodayPlease Move to the Next Session.

90

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | 91

Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | 92

top related