SlideShare une entreprise Scribd logo
1  sur  40
Télécharger pour lire hors ligne
Querydsl
Type-safe queries for Java
      Timo Westkämper
         @timowest
      www.querydsl.com
Before Querydsl

● Queries as strings within code

   TypedQuery<Person> query = em.createQuery(
      "select person from Person person " +
      "where person.firstName = ?1", Person.class);
   query.setParameter(1, "Max");
   List<Person> persons = query.getResultList();


● Must remember query syntax, domain classes,
  properties and relationships
   ●   Syntax reference always at hand
   ●   Domain model/schema reference at hand
   ●   High cognitive overhead
   ●   Error-prone
Before Querydsl

● Dynamic query building by string concatenation
  ● Very hard with multiple joins, ordering and complex
    conditionals depending on actual parameters

    StringBuilder where = new StringBuilder();
    if (firstName != null)
           where.append("person.firstName = :firstName");
    ...
    TypedQuery<Person> query = entityManager.createQuery(
           "select person from Person person where " + where,
           Person.class);
    if (firstName != null) query.setParameter("firstName", firstName);
    ...
    List<Person> persons = query.getResultList();
Before Querydsl

● Query syntax validation by execution is slow and
  breaks the flow
● Each back-end has its own query language and API
   ● SQL-like for JPA and JDO, but not for MongoDB
     and Lucene
● Verbose parameter binding by name or position to
  parameter placeholders of a prepared statement
   ● Or risk injection attack if parameters are directly
     concatenated to query
Before Querydsl

●   Hibernate Criteria API as an alternative?
    ●   Better for dynamic queries and has easier
        parameter binding, but...
    ●   Lacking expressivity, unintuitive, verbose,
        cognitive overhead for schema if not for syntax,
        not type-safe, slow validation...

●   Hibernate with three query languages to
    master with different focuses and expressivity
Querydsl

●   Domain model specific type-safe query language
    ● Compile time query validation
    ● Instant feedback on query errors
●   Compact and intuitive fluent syntax
    ● Syntactically close to SQL
    ● Great for dynamic query building


●   Supports multiple back-ends and query languages
    with consistent query API
    ● JPA/Hibernate, JDO, SQL, Lucene, Mongodb...
    ● Once you know basics of one language, you know
       basics of all SQL-like Querydsl languages
Querydsl

●   Autocomplete with Java IDEs
    ● No need to remember exact syntax
    ● No need to remember property names
●   Better support for domain model refactoring
    ● When domain changes, queries show compile
      errors
    ● Autocomplete helps fixing those
●   Developed for real-life projects, e.g. Balancion and
    Cyclos
●   Business friendly license (Apache 2.0)
Querydsl

●   Development started in 2007 with public releases since
    2008
●   Querydsl statistics:
     ● Approximately 24 000 LOC
     ● Test Code coverage about 75% (target 80%)
     ● Sonar reports
     ● FindBugs with extra annotations (@Nullable)
●   Discussions about standardisations
●   JDO/DataNucleus started with Querydsl...
Querydsl usage

●   Create your variables
    QPerson.person // default variable
    new QPerson("myPerson") // custom variable


●   Create your query
    JPAQuery, HibernateQuery, SQLQueryImpl etc


●   Populate your query
    from, where, groupBy, having, orderBy


●   Get the results
    count, iterate, list, uniqueResult
Querydsl usage

●   All expressions can be reused, immutables with
    caching – except BooleanBuilder and a few others

●   Queries, sub queries and BooleanBuilder are stateful
    builder with cascading methods
Overview of JPAQuery signature
from
    Query sources
innerJoin, join, leftJoin, fullJoin, on
    Join elements
    join(source, alias) [.on(source.prop.eq(alias.prop))]
where
   Query filters, varargs for intersection (and)
   and(), or(), allOf(), anyOf()
Overview of JPAQuery signature
groupBy
     Group by arguments in varargs form
having
     Having filter of the "group by” as an varags array of Predicate
     expressions.
orderBy
     Ordering of the result as an varargs array of order expressions.
     asc() and desc() on numeric, string and other comparable expression
limit, offset, restrict
     Paging of the result
     Limit for max results and Offset for skipping rows and
     Restrict for defining both in one call
Overview of JPAQuery signature
list
     Get the results as a typed List
listResults
     Get the results as a typed List and total row count for paging
iterate
     Get the results as a typed Iterator
count
     Get the row count as a long
uniqueResult
     Get a typed single row result
Simple example
QPerson person = QPerson.person;
JPAQuery query = new JPAQuery(entityManager);
List<Person> persons = query.from(person)
 .where(
   person.firstName.eq("John"),
   person.lastName.eq("Doe"))
 .list(person);

=>

select person from com.acme.Person person
where person.firstName eq = ?1 and person.lastName = ?2
Order
// Get persons ordered by last name and first name (desc)
query.from(person)
     .orderBy(person.lastName.asc(), person.firstName.desc())
     .list(person);

=>

select person from Person person
order by person.lastname asc, person.firstName desc
Order
// Get persons ordered by women first
query.from(person)
     .orderBy(person.gender
               .when(Gender.FEMALE).then(0)
               .otherwise(1).asc())
     .list(person);

=>

select person from Person person
order by case person.gender = Gender.FEMALE then 0 else 1 end asc
Grouping
// Get person counts grouped by last name
query.from(person)
   .groupBy(person.lastName)
   .list(person.lastName, person.count());

=>

select person.lastName, count(person) from Person person
group by person.lastName
Subqueries
//Get persons with max child count
QPerson parent = new QPerson("parent");
query.from(person)
   .where(person.children.size().eq(
       new JPASubQuery().from(parent)
                     .uniqueResult(parent.children.size().max())
    )).list(person);

=>

select person from Person person
where person.children.size() = (
  select max(parent.children.size()) from Person parent)
Constructor projection
// DTO class with @QueryProjection constructor annotation
public class PersonInfo {
   long id;
   String name;
   @QueryProjection
   public PersonInfo(long id, String name) {
     this.id = id;
     this.name = name;
   }
}


// List PersonInfo DTOs
List<PersonInfo> infos = query.from(person)
       .list(new QPersonInfo(person.id,
                  person.lastName.concat(", ”).concat(person.firstName)));
Tuple projection
// List ages of persons
List<Tuple> tuples = query.from(person)
.list(new QTuple(
    person.lastName,
    person.firstName,
    person.yearOfBirth));


for (Tuple tuple : tuples){
  // Typed access to mapped query results!
  String name = tuple.get(person.firstName) +
     " " + tuple.get(person.lastName);
  int age = tuple.get(person.yearOfBirth)
     - getCurrentYear();
  System.out.println(name + " is " + age + " years");
}
BooleanBuilder

●   Helper for building complex Boolean expressions
    dynamically

    BooleanBuilder nameDisjunction = new BooleanBuilder();
    for (String name : names) {
       nameDisjunction.or(person.firstName.like(name));
       nameDisjunction.or(person.lastName.like(name));
    }
    query.where(nameDisjunction);
Update
// Set firstName of all Does to John
long updatedRowCount =
new JPAUpdateClause(getEntityManager(), person)
   .set(person.firstName, "John")
   .where(person.lastName.eq("Doe"))
   .execute();

=>

update Person person
set person.firstName = ?1
where person.lastName = ?2
Delete
// Delete all John Does
long updatedRowCount =
new JPADeleteClause(getEntityManager(), person)
   .where(person.lastName.eq("Doe"),
      person.firstName.eq("John"))
   .execute();

=>

delete Person person
where person.lastName = ?1 and person.firstName = ?2
Querydsl extensions

●   Customize the code generation
    ● @QueryType(PropertyType.NONE)
       ● Non searchable
    ● @QueryType(PropertyType.SIMPLE)
       ● Equality comparisons only (eq, ne, in)
●   Custom query classes
    ● Extend abstract super classes and preserve fluent
      API
●   Custom expressions
    ● Static delegate methods with @QueryDelegate
    ● Template expressions for e.g. custom SQL
      functions
Querydsl extensions

●   Query serialization can be customized
    ● Works for JPA, JDO and SQL
    ● SQL dialects
    ● Overriding default templates (e.g.
      String#startsWith with like or regexp or...)
●   Expression DSL can be replaced
    ● E.g. Querydsl for Scala
●   Custom back-ends
    ● Lucene (10 classes) + Mongodb (6 classes)
Delegate methods
public class MyQueryExtensions {
  @QueryDelegate(Date.class)
  public static NumberExpression<Integer> yearAndMonth(DateTimePath<Date> date) {
     return date.year().multiply(100).add(date.month());
  }
}

=>

package ext.java.util;
...
public class QDate extends DateTimePath<java.util.Date> {
...
    public NumberExpression<Integer> yearAndMonth() {
      return MyQueryExtensions.yearAndMonth(this);
    }
}
Template expressions
// ilike
query.from(person)
.where(BooleanTemplate.create("{0} ilike {1}”,
    person.lastName, ConstantImpl.create("P%")))
.list(person);

=>

select person from Person person
where person.lastName ilike ?1
Custom query classes
public class PersonQuery extends AbstractJPAQuery<PersonQuery> {
  final QPerson person = QPerson.person;
  public PersonQuery(EntityManager em) {
     super(em);
     from(person);
  }
  public PersonQuery nameMatches(String name) {
     return where(person.firstName.like(name)
        .or(person.lastName.like(name)));
  }
}
JPA 2.0 Criteria vs Querydsl

●   JPA 2 Criteria is the standard for type-safe
    queries in JPA, but Querydsl is in our opinion
    superior in many ways
    ●   Easier and less verbose syntax
    ●   Customizable
    ●   Supports multiple back-ends – not just JPA
●   JPA has a difficult to use static query-model
    ●   Verbose property paths
    ●   Operations via builder object
●   Inverse order: “equals property value” vs.
    “property equals value”
    ●   Broken flow
Criteria example
// All possible pairs of single males and females
CriteriaQuery<Person> query = builder.createQuery(Person.class);
Root<Person> men = query.from( Person.class );
Root<Person> women = query.from( Person.class );
Predicate menRestriction = builder.and(
   builder.equal( men.get( Person_.gender ), Gender.MALE ),
   builder.equal( men.get( Person_.relationshipStatus ),
       RelationshipStatus.SINGLE )
);
Predicate womenRestriction = builder.and(
   builder.equal( women.get( Person_.gender ), Gender.FEMALE ),
   builder.equal( women.get( Person_.relationshipStatus ),
       RelationshipStatus.SINGLE )
);
query.where( builder.and( menRestriction, womenRestriction ) );
Querydsl example
// All possible pairs of single males and females
JPAQuery query = new JPAQuery(entityManager);
QPerson men = new QPerson("men");
QPerson women = new QPerson("women");
query.from(men, women).where(
       men.gender.eq(Gender.MALE),
       men.relationshipStatus.eq(RelationshipStatus.SINGLE),
       women.gender.eq(Gender.FEMALE),
       women.relationshipStatus.eq(RelationshipStatus.SINGLE));
SQL

●   Pretty similar to JPA/Hibernate
    ● No deep paths over relations though
    ● No implicit joins

     SQLTemplates templates = new MySQLTemplates();
     ...
         SQLQuery query = new SQLQueryImpl(connection,
    templates);
         query.from(person);
         query.innerJoin(parent).on(parent.id.eq(person.parent.id));

●   Shortcut for joins with foreign keys
         query.innerJoin(person.parentFK, parent);
SQL

●   Maven plugin for generating query model
●   Support for special SQL constructs and extensions

●   Databases supported include
    ●   MySQL
    ●   PostgreSQL
    ●   Oracle
    ●   MS SQL Server
    ●   H2
    ●   HSQLDB
    ●   Derby
    ●   SQLite
    ●   CUBRID
SQL extensions

●   Sub class of AbstractSQLQuery
    ● e.g. OracleQuery with connectByPrior
●   Template expressions
●   Direct addition of “flags”
    SQLInsertClause insert =
       new SQLInsertClause(connection, templates, person);
    insert.addFlag(Position.START_OVERRIDE, "replace into ");
JPA/Hibernate Maven
                 Integration
<build><plugins><plugin>
 <groupId>com.mysema.maven</groupId>
 <artifactId>maven-apt-plugin</artifactId>
 <version>1.0.3</version>
 <executions>
  <execution>
    <goals><goal>process</goal></goals>
    <configuration>
     <outputDirectory>target/generated-sources/java</outputDirectory>
     <processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor>
    </configuration>
  </execution>
 </executions>
</plugin></plugins></build>
SQL Maven Integration
<build><plugins><plugin>
 <groupId>com.mysema.querydsl</groupId>
 <artifactId>querydsl-maven-plugin</artifactId>
 <version>${querydsl.version}</version>
 <executions><execution>
  <goals><goal>export</goal></goals>
 </execution></executions>
 <configuration>
  <jdbcDriver>org.apache.derby.jdbc.EmbeddedDriver</jdbcDriver>
  <jdbcUrl>jdbc:derby:target/demoDB;create=true</jdbcUrl>
  <!—- optional elements : namePrefix, jdbcUser, jdbcPassword, schemaPattern, tableNamePattern -->
  <packageName>com.myproject.domain</packageName>
  <targetFolder>${project.basedir}/target/generated-sources/java</targetFolder>
 </configuration>
 <dependencies><dependency>
  <!—- jdbc driver dependency -->
  <groupId>org.apache.derby</groupId>
  <artifactId>derby</artifactId>
  <version>${derby.version}</version>
 </dependency></dependencies>
</plugin></plugins></build>
What does Mysema offer for
           Querydsl?
● Free public support
  ● GitHub Issues
  ● Querydsl Google Group
  ● Mysema Blog
● Consulting services
  ● User support
  ● Custom extensions and integration
  ● Training
Querydsl support from other
            companies
●   VMware uses Querydsl in Spring Data for the
    following backends
     ● JPA
     ● SQL/JDBC
     ● MongoDB
     ● Neo4j
●   Spring Data is a good option if you want to use
    repositories in Spring with Querydsl support
Questions?
Thanks!

Timo Westkämper
   @timowest
www.querydsl.com
www.mysema.com

Contenu connexe

Tendances

文字コードの脆弱性はこの3年間でどの程度対策されたか?
文字コードの脆弱性はこの3年間でどの程度対策されたか?文字コードの脆弱性はこの3年間でどの程度対策されたか?
文字コードの脆弱性はこの3年間でどの程度対策されたか?
Hiroshi Tokumaru
 

Tendances (20)

PostgreSQL Materialized Views with Active Record
PostgreSQL Materialized Views with Active RecordPostgreSQL Materialized Views with Active Record
PostgreSQL Materialized Views with Active Record
 
Php internal architecture
Php internal architecturePhp internal architecture
Php internal architecture
 
文字コードの脆弱性はこの3年間でどの程度対策されたか?
文字コードの脆弱性はこの3年間でどの程度対策されたか?文字コードの脆弱性はこの3年間でどの程度対策されたか?
文字コードの脆弱性はこの3年間でどの程度対策されたか?
 
Models for hierarchical data
Models for hierarchical dataModels for hierarchical data
Models for hierarchical data
 
Regular Expressions Cheat Sheet
Regular Expressions Cheat SheetRegular Expressions Cheat Sheet
Regular Expressions Cheat Sheet
 
Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009
 
Clean code in JavaScript
Clean code in JavaScriptClean code in JavaScript
Clean code in JavaScript
 
Distributed Load Testing with k6 - DevOps Barcelona
Distributed Load Testing with k6 - DevOps BarcelonaDistributed Load Testing with k6 - DevOps Barcelona
Distributed Load Testing with k6 - DevOps Barcelona
 
Monadic Java
Monadic JavaMonadic Java
Monadic Java
 
Clean Lambdas & Streams in Java8
Clean Lambdas & Streams in Java8Clean Lambdas & Streams in Java8
Clean Lambdas & Streams in Java8
 
clean code book summary - uncle bob - English version
clean code book summary - uncle bob - English versionclean code book summary - uncle bob - English version
clean code book summary - uncle bob - English version
 
Java and OWL
Java and OWLJava and OWL
Java and OWL
 
[2018] MyBatis에서 JPA로
[2018] MyBatis에서 JPA로[2018] MyBatis에서 JPA로
[2018] MyBatis에서 JPA로
 
Text classification presentation
Text classification presentationText classification presentation
Text classification presentation
 
Clean Code
Clean CodeClean Code
Clean Code
 
[Pgday.Seoul 2020] SQL Tuning
[Pgday.Seoul 2020] SQL Tuning[Pgday.Seoul 2020] SQL Tuning
[Pgday.Seoul 2020] SQL Tuning
 
Functional Patterns with Java8 @Bucharest Java User Group
Functional Patterns with Java8 @Bucharest Java User GroupFunctional Patterns with Java8 @Bucharest Java User Group
Functional Patterns with Java8 @Bucharest Java User Group
 
CQL - Cassandra commands Notes
CQL - Cassandra commands NotesCQL - Cassandra commands Notes
CQL - Cassandra commands Notes
 
2017 Pycon KR - Django/AWS 를 이용한 쇼핑몰 서비스 구축
2017 Pycon KR - Django/AWS 를 이용한 쇼핑몰 서비스 구축2017 Pycon KR - Django/AWS 를 이용한 쇼핑몰 서비스 구축
2017 Pycon KR - Django/AWS 를 이용한 쇼핑몰 서비스 구축
 
[Pgday.Seoul 2021] 1. 예제로 살펴보는 포스트그레스큐엘의 독특한 SQL
[Pgday.Seoul 2021] 1. 예제로 살펴보는 포스트그레스큐엘의 독특한 SQL[Pgday.Seoul 2021] 1. 예제로 살펴보는 포스트그레스큐엘의 독특한 SQL
[Pgday.Seoul 2021] 1. 예제로 살펴보는 포스트그레스큐엘의 독특한 SQL
 

Similaire à Querydsl fin jug - june 2012

Easy data-with-spring-data-jpa
Easy data-with-spring-data-jpaEasy data-with-spring-data-jpa
Easy data-with-spring-data-jpa
Staples
 
Jpa queries
Jpa queriesJpa queries
Jpa queries
gedoplan
 
Sql Patterns
Sql PatternsSql Patterns
Sql Patterns
phanleson
 
Laurens Van Den Oever Xopus Presentation
Laurens Van Den Oever Xopus PresentationLaurens Van Den Oever Xopus Presentation
Laurens Van Den Oever Xopus Presentation
Ajax Experience 2009
 
Embedded Typesafe Domain Specific Languages for Java
Embedded Typesafe Domain Specific Languages for JavaEmbedded Typesafe Domain Specific Languages for Java
Embedded Typesafe Domain Specific Languages for Java
Jevgeni Kabanov
 

Similaire à Querydsl fin jug - june 2012 (20)

Data access 2.0? Please welcome: Spring Data!
Data access 2.0? Please welcome: Spring Data!Data access 2.0? Please welcome: Spring Data!
Data access 2.0? Please welcome: Spring Data!
 
ORM JPA
ORM JPAORM JPA
ORM JPA
 
An introduction into Spring Data
An introduction into Spring DataAn introduction into Spring Data
An introduction into Spring Data
 
Beyond java8
Beyond java8Beyond java8
Beyond java8
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
 
Easy data-with-spring-data-jpa
Easy data-with-spring-data-jpaEasy data-with-spring-data-jpa
Easy data-with-spring-data-jpa
 
Hibernate
Hibernate Hibernate
Hibernate
 
Jpa queries
Jpa queriesJpa queries
Jpa queries
 
Http4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web StackHttp4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web Stack
 
Polyglot persistence with Spring Data
Polyglot persistence with Spring DataPolyglot persistence with Spring Data
Polyglot persistence with Spring Data
 
Hadoop Integration in Cassandra
Hadoop Integration in CassandraHadoop Integration in Cassandra
Hadoop Integration in Cassandra
 
Sql Patterns
Sql PatternsSql Patterns
Sql Patterns
 
Building a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceBuilding a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to Space
 
JavaOne 2017 - JNoSQL: The Definitive Solution for Java and NoSQL Database [C...
JavaOne 2017 - JNoSQL: The Definitive Solution for Java and NoSQL Database [C...JavaOne 2017 - JNoSQL: The Definitive Solution for Java and NoSQL Database [C...
JavaOne 2017 - JNoSQL: The Definitive Solution for Java and NoSQL Database [C...
 
Java Annotation Processing: A Beginner Walkthrough
Java Annotation Processing: A Beginner WalkthroughJava Annotation Processing: A Beginner Walkthrough
Java Annotation Processing: A Beginner Walkthrough
 
Requery overview
Requery overviewRequery overview
Requery overview
 
Laurens Van Den Oever Xopus Presentation
Laurens Van Den Oever Xopus PresentationLaurens Van Den Oever Xopus Presentation
Laurens Van Den Oever Xopus Presentation
 
NLJUG University Sessie: Java Reborn, Powered by Ordina
NLJUG University Sessie: Java Reborn, Powered by OrdinaNLJUG University Sessie: Java Reborn, Powered by Ordina
NLJUG University Sessie: Java Reborn, Powered by Ordina
 
Embedded Typesafe Domain Specific Languages for Java
Embedded Typesafe Domain Specific Languages for JavaEmbedded Typesafe Domain Specific Languages for Java
Embedded Typesafe Domain Specific Languages for Java
 
NoSQL Endgame Percona Live Online 2020
NoSQL Endgame Percona Live Online 2020NoSQL Endgame Percona Live Online 2020
NoSQL Endgame Percona Live Online 2020
 

Dernier

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 

Dernier (20)

CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 

Querydsl fin jug - june 2012

  • 1. Querydsl Type-safe queries for Java Timo Westkämper @timowest www.querydsl.com
  • 2. Before Querydsl ● Queries as strings within code TypedQuery<Person> query = em.createQuery( "select person from Person person " + "where person.firstName = ?1", Person.class); query.setParameter(1, "Max"); List<Person> persons = query.getResultList(); ● Must remember query syntax, domain classes, properties and relationships ● Syntax reference always at hand ● Domain model/schema reference at hand ● High cognitive overhead ● Error-prone
  • 3. Before Querydsl ● Dynamic query building by string concatenation ● Very hard with multiple joins, ordering and complex conditionals depending on actual parameters StringBuilder where = new StringBuilder(); if (firstName != null) where.append("person.firstName = :firstName"); ... TypedQuery<Person> query = entityManager.createQuery( "select person from Person person where " + where, Person.class); if (firstName != null) query.setParameter("firstName", firstName); ... List<Person> persons = query.getResultList();
  • 4. Before Querydsl ● Query syntax validation by execution is slow and breaks the flow ● Each back-end has its own query language and API ● SQL-like for JPA and JDO, but not for MongoDB and Lucene ● Verbose parameter binding by name or position to parameter placeholders of a prepared statement ● Or risk injection attack if parameters are directly concatenated to query
  • 5. Before Querydsl ● Hibernate Criteria API as an alternative? ● Better for dynamic queries and has easier parameter binding, but... ● Lacking expressivity, unintuitive, verbose, cognitive overhead for schema if not for syntax, not type-safe, slow validation... ● Hibernate with three query languages to master with different focuses and expressivity
  • 6. Querydsl ● Domain model specific type-safe query language ● Compile time query validation ● Instant feedback on query errors ● Compact and intuitive fluent syntax ● Syntactically close to SQL ● Great for dynamic query building ● Supports multiple back-ends and query languages with consistent query API ● JPA/Hibernate, JDO, SQL, Lucene, Mongodb... ● Once you know basics of one language, you know basics of all SQL-like Querydsl languages
  • 7. Querydsl ● Autocomplete with Java IDEs ● No need to remember exact syntax ● No need to remember property names ● Better support for domain model refactoring ● When domain changes, queries show compile errors ● Autocomplete helps fixing those ● Developed for real-life projects, e.g. Balancion and Cyclos ● Business friendly license (Apache 2.0)
  • 8. Querydsl ● Development started in 2007 with public releases since 2008 ● Querydsl statistics: ● Approximately 24 000 LOC ● Test Code coverage about 75% (target 80%) ● Sonar reports ● FindBugs with extra annotations (@Nullable) ● Discussions about standardisations ● JDO/DataNucleus started with Querydsl...
  • 9. Querydsl usage ● Create your variables QPerson.person // default variable new QPerson("myPerson") // custom variable ● Create your query JPAQuery, HibernateQuery, SQLQueryImpl etc ● Populate your query from, where, groupBy, having, orderBy ● Get the results count, iterate, list, uniqueResult
  • 10. Querydsl usage ● All expressions can be reused, immutables with caching – except BooleanBuilder and a few others ● Queries, sub queries and BooleanBuilder are stateful builder with cascading methods
  • 11. Overview of JPAQuery signature from Query sources innerJoin, join, leftJoin, fullJoin, on Join elements join(source, alias) [.on(source.prop.eq(alias.prop))] where Query filters, varargs for intersection (and) and(), or(), allOf(), anyOf()
  • 12. Overview of JPAQuery signature groupBy Group by arguments in varargs form having Having filter of the "group by” as an varags array of Predicate expressions. orderBy Ordering of the result as an varargs array of order expressions. asc() and desc() on numeric, string and other comparable expression limit, offset, restrict Paging of the result Limit for max results and Offset for skipping rows and Restrict for defining both in one call
  • 13. Overview of JPAQuery signature list Get the results as a typed List listResults Get the results as a typed List and total row count for paging iterate Get the results as a typed Iterator count Get the row count as a long uniqueResult Get a typed single row result
  • 14. Simple example QPerson person = QPerson.person; JPAQuery query = new JPAQuery(entityManager); List<Person> persons = query.from(person) .where( person.firstName.eq("John"), person.lastName.eq("Doe")) .list(person); => select person from com.acme.Person person where person.firstName eq = ?1 and person.lastName = ?2
  • 15. Order // Get persons ordered by last name and first name (desc) query.from(person) .orderBy(person.lastName.asc(), person.firstName.desc()) .list(person); => select person from Person person order by person.lastname asc, person.firstName desc
  • 16. Order // Get persons ordered by women first query.from(person) .orderBy(person.gender .when(Gender.FEMALE).then(0) .otherwise(1).asc()) .list(person); => select person from Person person order by case person.gender = Gender.FEMALE then 0 else 1 end asc
  • 17. Grouping // Get person counts grouped by last name query.from(person) .groupBy(person.lastName) .list(person.lastName, person.count()); => select person.lastName, count(person) from Person person group by person.lastName
  • 18. Subqueries //Get persons with max child count QPerson parent = new QPerson("parent"); query.from(person) .where(person.children.size().eq( new JPASubQuery().from(parent) .uniqueResult(parent.children.size().max()) )).list(person); => select person from Person person where person.children.size() = ( select max(parent.children.size()) from Person parent)
  • 19. Constructor projection // DTO class with @QueryProjection constructor annotation public class PersonInfo { long id; String name; @QueryProjection public PersonInfo(long id, String name) { this.id = id; this.name = name; } } // List PersonInfo DTOs List<PersonInfo> infos = query.from(person) .list(new QPersonInfo(person.id, person.lastName.concat(", ”).concat(person.firstName)));
  • 20. Tuple projection // List ages of persons List<Tuple> tuples = query.from(person) .list(new QTuple( person.lastName, person.firstName, person.yearOfBirth)); for (Tuple tuple : tuples){ // Typed access to mapped query results! String name = tuple.get(person.firstName) + " " + tuple.get(person.lastName); int age = tuple.get(person.yearOfBirth) - getCurrentYear(); System.out.println(name + " is " + age + " years"); }
  • 21. BooleanBuilder ● Helper for building complex Boolean expressions dynamically BooleanBuilder nameDisjunction = new BooleanBuilder(); for (String name : names) { nameDisjunction.or(person.firstName.like(name)); nameDisjunction.or(person.lastName.like(name)); } query.where(nameDisjunction);
  • 22. Update // Set firstName of all Does to John long updatedRowCount = new JPAUpdateClause(getEntityManager(), person) .set(person.firstName, "John") .where(person.lastName.eq("Doe")) .execute(); => update Person person set person.firstName = ?1 where person.lastName = ?2
  • 23. Delete // Delete all John Does long updatedRowCount = new JPADeleteClause(getEntityManager(), person) .where(person.lastName.eq("Doe"), person.firstName.eq("John")) .execute(); => delete Person person where person.lastName = ?1 and person.firstName = ?2
  • 24. Querydsl extensions ● Customize the code generation ● @QueryType(PropertyType.NONE) ● Non searchable ● @QueryType(PropertyType.SIMPLE) ● Equality comparisons only (eq, ne, in) ● Custom query classes ● Extend abstract super classes and preserve fluent API ● Custom expressions ● Static delegate methods with @QueryDelegate ● Template expressions for e.g. custom SQL functions
  • 25. Querydsl extensions ● Query serialization can be customized ● Works for JPA, JDO and SQL ● SQL dialects ● Overriding default templates (e.g. String#startsWith with like or regexp or...) ● Expression DSL can be replaced ● E.g. Querydsl for Scala ● Custom back-ends ● Lucene (10 classes) + Mongodb (6 classes)
  • 26. Delegate methods public class MyQueryExtensions { @QueryDelegate(Date.class) public static NumberExpression<Integer> yearAndMonth(DateTimePath<Date> date) { return date.year().multiply(100).add(date.month()); } } => package ext.java.util; ... public class QDate extends DateTimePath<java.util.Date> { ... public NumberExpression<Integer> yearAndMonth() { return MyQueryExtensions.yearAndMonth(this); } }
  • 27. Template expressions // ilike query.from(person) .where(BooleanTemplate.create("{0} ilike {1}”, person.lastName, ConstantImpl.create("P%"))) .list(person); => select person from Person person where person.lastName ilike ?1
  • 28. Custom query classes public class PersonQuery extends AbstractJPAQuery<PersonQuery> { final QPerson person = QPerson.person; public PersonQuery(EntityManager em) { super(em); from(person); } public PersonQuery nameMatches(String name) { return where(person.firstName.like(name) .or(person.lastName.like(name))); } }
  • 29. JPA 2.0 Criteria vs Querydsl ● JPA 2 Criteria is the standard for type-safe queries in JPA, but Querydsl is in our opinion superior in many ways ● Easier and less verbose syntax ● Customizable ● Supports multiple back-ends – not just JPA ● JPA has a difficult to use static query-model ● Verbose property paths ● Operations via builder object ● Inverse order: “equals property value” vs. “property equals value” ● Broken flow
  • 30. Criteria example // All possible pairs of single males and females CriteriaQuery<Person> query = builder.createQuery(Person.class); Root<Person> men = query.from( Person.class ); Root<Person> women = query.from( Person.class ); Predicate menRestriction = builder.and( builder.equal( men.get( Person_.gender ), Gender.MALE ), builder.equal( men.get( Person_.relationshipStatus ), RelationshipStatus.SINGLE ) ); Predicate womenRestriction = builder.and( builder.equal( women.get( Person_.gender ), Gender.FEMALE ), builder.equal( women.get( Person_.relationshipStatus ), RelationshipStatus.SINGLE ) ); query.where( builder.and( menRestriction, womenRestriction ) );
  • 31. Querydsl example // All possible pairs of single males and females JPAQuery query = new JPAQuery(entityManager); QPerson men = new QPerson("men"); QPerson women = new QPerson("women"); query.from(men, women).where( men.gender.eq(Gender.MALE), men.relationshipStatus.eq(RelationshipStatus.SINGLE), women.gender.eq(Gender.FEMALE), women.relationshipStatus.eq(RelationshipStatus.SINGLE));
  • 32. SQL ● Pretty similar to JPA/Hibernate ● No deep paths over relations though ● No implicit joins SQLTemplates templates = new MySQLTemplates(); ... SQLQuery query = new SQLQueryImpl(connection, templates); query.from(person); query.innerJoin(parent).on(parent.id.eq(person.parent.id)); ● Shortcut for joins with foreign keys query.innerJoin(person.parentFK, parent);
  • 33. SQL ● Maven plugin for generating query model ● Support for special SQL constructs and extensions ● Databases supported include ● MySQL ● PostgreSQL ● Oracle ● MS SQL Server ● H2 ● HSQLDB ● Derby ● SQLite ● CUBRID
  • 34. SQL extensions ● Sub class of AbstractSQLQuery ● e.g. OracleQuery with connectByPrior ● Template expressions ● Direct addition of “flags” SQLInsertClause insert = new SQLInsertClause(connection, templates, person); insert.addFlag(Position.START_OVERRIDE, "replace into ");
  • 35. JPA/Hibernate Maven Integration <build><plugins><plugin> <groupId>com.mysema.maven</groupId> <artifactId>maven-apt-plugin</artifactId> <version>1.0.3</version> <executions> <execution> <goals><goal>process</goal></goals> <configuration> <outputDirectory>target/generated-sources/java</outputDirectory> <processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor> </configuration> </execution> </executions> </plugin></plugins></build>
  • 36. SQL Maven Integration <build><plugins><plugin> <groupId>com.mysema.querydsl</groupId> <artifactId>querydsl-maven-plugin</artifactId> <version>${querydsl.version}</version> <executions><execution> <goals><goal>export</goal></goals> </execution></executions> <configuration> <jdbcDriver>org.apache.derby.jdbc.EmbeddedDriver</jdbcDriver> <jdbcUrl>jdbc:derby:target/demoDB;create=true</jdbcUrl> <!—- optional elements : namePrefix, jdbcUser, jdbcPassword, schemaPattern, tableNamePattern --> <packageName>com.myproject.domain</packageName> <targetFolder>${project.basedir}/target/generated-sources/java</targetFolder> </configuration> <dependencies><dependency> <!—- jdbc driver dependency --> <groupId>org.apache.derby</groupId> <artifactId>derby</artifactId> <version>${derby.version}</version> </dependency></dependencies> </plugin></plugins></build>
  • 37. What does Mysema offer for Querydsl? ● Free public support ● GitHub Issues ● Querydsl Google Group ● Mysema Blog ● Consulting services ● User support ● Custom extensions and integration ● Training
  • 38. Querydsl support from other companies ● VMware uses Querydsl in Spring Data for the following backends ● JPA ● SQL/JDBC ● MongoDB ● Neo4j ● Spring Data is a good option if you want to use repositories in Spring with Querydsl support
  • 40. Thanks! Timo Westkämper @timowest www.querydsl.com www.mysema.com