Jpa queries

318 Aufrufe

Veröffentlicht am

0 Kommentare
0 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

  • Gehören Sie zu den Ersten, denen das gefällt!

Keine Downloads
Aufrufe
Aufrufe insgesamt
318
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
2
Aktionen
Geteilt
0
Downloads
6
Kommentare
0
Gefällt mir
0
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

Jpa queries

  1. 1. Java Persistence Queries Effektive DB-Abfragen mit Features aus dem Standard und darüber hinaus Expertenkreis Java, 18.06.2015, GEDOPLAN Dirk Weil, GEDOPLAN GmbH
  2. 2. Dirk Weil GEDOPLAN GmbH, Bielefeld Java EE seit 1998 Konzeption und Realisierung Seminare Vorträge Veröffentlichungen Java Persistence Queries 2
  3. 3. Java Persistence Mapping OO  RDBMS POJOs Detachment macht DTOs verzichtbar API zum Speichern, Laden, Löschen, Finden von DB- Einträgen Eclipselink, Hibernate, OpenJPA, … Seit Java EE 5 im Standard Auch in SE nutzbar Aktuelle Version 2.1 3Java Persistence Queries
  4. 4. Demo-Entities 4Java Persistence Queries @Entity public class Publisher { @Id private Integer id; private String name; @ManyToOne private Country country; @OneToMany(mappedBy = "publisher") private List<Book> books; @Entity public class Book { @Id private Integer id; private String name; private String isbn; private int pages; @ManyToOne private Publisher publisher; 1 n @Entity public class Country { @Id @Column(name = "ISO_CODE") private String isoCode; private String name;n 1
  5. 5. JPQL Java Persistence Query Language SQL-ähnlich, jedoch objektorientiert EntityManager.createQuery liefert TypedQuery<T> Ausführung mit getSingleResult bzw. getResultList 5Java Persistence Queries Publisher publisher = entityManager .createQuery("select p from Publisher p where p.name=?1", Publisher.class) .setParameter(1, "O'Melly Publishing") .getSingleResult(); List<Book> books = entityManager .createQuery("select b from Book b where b.pages>=500", Book.class) .getResultList();
  6. 6. JPQL Navigation durch Relationen mit '.' und join 6Java Persistence Queries List<Book> books = entityManager .createQuery("select b from Book b where b.publisher.country=?1", Book.class) .setParameter(1, countryDE) .getResultList(); List<Publisher> publishers = entityManager .createQuery("select distinct p from Publisher p " + "join p.books b where b.pages>=500", Publisher.class) .getResultList();
  7. 7. JPQL JPQL  SQL "leichtgewichtig" 7Java Persistence Queries List<Publisher> publishers = entityManager .createQuery("select distinct p from Publisher p " + "join p.books b where b.pages>=500", Publisher.class) .getResultList(); SELECT DISTINCT t1.ID, t1.NAME, t1.COUNTRY_ISO_CODE FROM JPA_BOOK t0, JPA_PUBLISHER t1 WHERE ((t0.PAGES >= ?) AND (t0.PUBLISHER_ID = t1.ID)) select distinct publisher0_.ID as ID1_35_, publisher0_.COUNTRY_ISO_CODE as COUNTRY_3_35_, publisher0_.name as name2_35_ from JPA_PUBLISHER publisher0_ inner join JPA_BOOK books1_ on publisher0_.ID=books1_.publisher_ID where books1_.pages>=500 Eclipselink Hibernate
  8. 8. Extended Queries Selektion von Einzelattributen etc. 8Java Persistence Queries List<Object[]> resultList = entityManager .createQuery("select p.name, p.country.name from Publisher p", Object[].class) .getResultList(); List<Object[]> resultList = entityManager .createQuery("select p, count(b) from Publisher p " + "left join p.books b " + "group by p", Object[].class) .getResultList();
  9. 9. Extended Queries Selektion von Einzelattributen etc. 9Java Persistence Queries List<NameAndCount> resultList = entityManager .createQuery("select new somepkg.NameAndCount(p.name, sum(b.pages)) " + "from Publisher p " + "join p.books b " + "where b.name like '%Java%' " + "group by p", NameAndCount.class) .getResultList(); public class NameAndCount { private String name; private Number count; public NameAndCount(String name, Number count) {
  10. 10. Native Queries bei schon vorhandenen SQL-Queries für "besondere Fälle" (proprietäres SQL, spezielles Tuning, …) "Verlust" des O/R-Mappings auch Komplettobjekte als Ergebnis möglich 10Java Persistence Queries @SuppressWarnings("unchecked") List<Object[]> resultList = entityManager .createNativeQuery("SELECT DISTINCT p.ID, p.NAME, p.COUNTRY_ISO_CODE " + "FROM JPA_PUBLISHER p, JPA_BOOK b " + "WHERE b.PUBLISHER_ID = p.ID AND b.PAGES >= ?") .setParameter(1, 500) .getResultList();
  11. 11. Stored Procedure Queries für "noch besonderere Fälle" IN-, OUT- oder IN/OUT-Parameter 11Java Persistence Queries CREATE PROCEDURE GET_COCKTAIL_COUNT(IN ZUTAT_NAME VARCHAR(255)) BEGIN select count(*) from JPA_COCKTAIL C where exists (…); END Number count = (Number) entityManager .createStoredProcedureQuery("GET_COCKTAIL_COUNT") .registerStoredProcedureParameter("ZUTAT_NAME", String.class, ParameterMode.IN) .setParameter("ZUTAT_NAME", "Sekt") .getSingleResult();
  12. 12. Criteria Query API Textbasierte Queries lassen sich zur Compile- oder Deploymentzeit nicht prüfen Syntax Namen Typen 12Java Persistence Queries select p fron Publisher p select p from Publisher select p from Publisher p where p.nam=:name List<Publisher> books = entityManager .createQuery("select b from Book b where b.pages>=500", Publisher.class) .getResultList();
  13. 13. Criteria Query API Query wird mittels API kombiniert CriteriaQuery<T> mittels CriteriaBuilder erstellen from, where, select … Ausführung als "normale" TypedQuery<T> 13Java Persistence Queries CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<Book> cq = cb.createQuery(Book.class); List<Book> books = this.entityManager .createQuery(cq) .getResultList();
  14. 14. Criteria Query API 14Java Persistence Queries // select b from Book b where b.pages>=500 Root<Book> b = cq.from(Book.class); cq.select(b) .where(cb.greaterThanOrEqualTo(b.get(Book_.pages), 500)); // select b from Book b where b.publisher.country=:country Root<Book> b = cq.from(Book.class); cq.select(b) .where(cb.equal(b.get(Book_.publisher).get(Publisher_.country), cb.parameter(Country.class, "country"))); List<Book> books = this.entityManager .createQuery(cq) .setParameter("country", CountryTest.testCountryDE) .getResultList();
  15. 15. Criteria Query API nutzt statisches Metamodell E_ zu persistenter Klasse E 15Java Persistence Queries @StaticMetamodel(Publisher.class) public abstract class Publisher_ { public static volatile SingularAttribute<GeneratedIntegerIdEntity, Integer> id; public static volatile SingularAttribute<Publisher, String> name; public static volatile SingularAttribute<Publisher, Country> country; public static volatile ListAttribute<Publisher, Book> books; @Entity public class Publisher { @Id private Integer id; private String name; @ManyToOne private Country country; @OneToMany(mappedBy = "publisher") private List<Book> books;
  16. 16. Criteria Query API Metamodell wird durch Annotation Processor generiert muss im Compile Classpath liegen (z. B. als Maven Dependency) wird vom Compiler aufgerufen (Java 6+) 16Java Persistence Queries <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-jpamodelgen</artifactId> <version>4.3.10.Final</version> <scope>provided</scope> <optional>true</optional> </dependency>
  17. 17. Criteria Query API Annotation Processing in Eclipse kann in Luna entsprechend Maven konfiguriert werden sonst: Im Projekt Annotation Processing manuell konfigurieren Java Compiler  Annotation Processing aktivieren, Zielordner wählen  Factory Path Compile Classpath einstellen 17Java Persistence Queries
  18. 18. Root<Publisher> p = cq.from(Publisher.class); ListJoin<Publisher, Book> b = p.join(Publisher_.books); cq.select(cb.construct(NameAndCount.class, p.get(Publisher_.name), cb.sum(b.get(Book_.pages)))) .where(cb.like(b.get(Book_.name), "%Java%")) .groupBy(p); Criteria Query API Problem: Lesbarkeit 18Java Persistence Queries // select new NameAndCount(p.name, sum(b.pages)) // from Publisher p // join p.books b // where b.name like '%Java%' // group by p
  19. 19. Root<Publisher> p = cq.from(Publisher.class); ListJoin<Publisher, Book> b = p.join(Publisher_.books); cq.select(p.get(Publisher_.name)) .distinct(true) .where(cb.and(cb.equal(p.get(Publisher_.country), cb.parameter(Country.class, "country")), cb.like(b.get(Book_.name), "%Java%"))); Criteria Query API Problem: API durch CriteriaBuilder (u. a.) nicht "fluent" 19Java Persistence Queries p ~ Publisher; b ~ p.books; c ~ Parameter(Country); select(p.name) .distinct() .from(p) .where(p.country.equal(c).and(b.name.like("%Java%"))) Wunsch Ist
  20. 20. QueryDSL Open Source (http://www.querydsl.com) Sponsored by Mysema (http://www.mysema.com) Query wird mittels API kombiniert Query Roots und JPAQuery für EntityManager erzeugen Methoden from, join, where, orderBy, distinct etc. Query ausführen mittels singleResult, list 20Java Persistence Queries QPublisher p = QPublisher.publisher; JPAQuery jpaQuery = new JPAQuery(this.entityManager) List<Publisher> result = jpaQuery.list(p);
  21. 21. QueryDSL benötigt generierte Klassen ähnlich JPA Metamodell 21Java Persistence Queries @Generated("com.mysema.query.codegen.EntitySerializer") public class QPublisher extends EntityPathBase<Publisher> { public static final QPublisher publisher = new QPublisher("publisher"); public final StringPath name = createString("name"); public final ListPath<Book, QBook> books = this.<Book, QBook>createList("books", … public final de.gedoplan.seminar.jpa.demo.basics.entity.QCountry country; @Entity public class Publisher { @Id private Integer id; private String name; @ManyToOne private Country country; @OneToMany(mappedBy = "publisher") private List<Book> books;
  22. 22. QueryDSL Metamodell wird durch Annotation Processor generiert z. B. mit Maven Plugin 22Java Persistence Queries <plugin> <groupId>com.mysema.maven</groupId> <artifactId>apt-maven-plugin</artifactId> <version>1.1.3</version> <executions> <execution> <goals><goal>process</goal></goals> <configuration> <outputDirectory>target/generated-sources/annotations</outputDirectory> <processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor> </configuration> </execution> </executions> </plugin>
  23. 23. QueryDSL 23Java Persistence Queries QPublisher p = QPublisher.publisher; QBook b = QBook.book; Param<Country> countryParam = new Param<>(Country.class); List<String> names = new JPAQuery(this.entityManager) .from(p) .innerJoin(p.books, b) .where(p.country.eq(countryParam).and(b.name.like("%Java%"))) .distinct() .set(countryParam, CountryTest.testCountryDE) .list(p.name); Root<Publisher> p = cq.from(Publisher.class); ListJoin<Publisher, Book> b = p.join(Publisher_.books); cq.select(p.get(Publisher_.name)) .distinct(true) .where(cb.and(cb.equal(p.get(Publisher_.country), cb.parameter(Country.class, "country")), cb.like(b.get(Book_.name), "%Java%"))); QueryDSL Criteri a Query API
  24. 24. QueryDSL Bisherige Erfahrungen Intuitives API (meist …) gute Lesbarkeit API hat noch Schwächen z. B. Umwandlung von JPAQuery nur in Query möglich, nicht in TypedQuery Noch nicht ganz ausgereift einige Bugs (z. B. Constructor Result akzeptiert keine Aggregat- Ausdrücke) Dokumentation lückenhaft und fehlerhaft Umstellung com.mysema.querydsl  com.querydsl buggy 24Java Persistence Queries
  25. 25. More http://www.gedoplan-it-training.de Seminare in Berlin, Bielefeld, Inhouse http://www.gedoplan-it-consulting.de Reviews, Coaching, … http://javaeeblog.wordpress.com/ http://expertenkreisjava.blogspot.de/  dirk.weil@gedoplan.de @dirkweil Java Persistence Queries 25

×