SlideShare ist ein Scribd-Unternehmen logo
1 von 40
Downloaden Sie, um offline zu lesen
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

Weitere ähnliche Inhalte

Was ist angesagt?

Was ist angesagt? (20)

Meetup React Sanca - 29/11/18 - React Testing
Meetup React Sanca - 29/11/18 - React TestingMeetup React Sanca - 29/11/18 - React Testing
Meetup React Sanca - 29/11/18 - React Testing
 
前端爆肝之旅+React上山前的小專案心得分享
前端爆肝之旅+React上山前的小專案心得分享前端爆肝之旅+React上山前的小專案心得分享
前端爆肝之旅+React上山前的小專案心得分享
 
GraphQL Introduction
GraphQL IntroductionGraphQL Introduction
GraphQL Introduction
 
JavaScript TDD with Jasmine and Karma
JavaScript TDD with Jasmine and KarmaJavaScript TDD with Jasmine and Karma
JavaScript TDD with Jasmine and Karma
 
Graphql
GraphqlGraphql
Graphql
 
The tests are trying to tell you something@VoxxedBucharest.pptx
The tests are trying to tell you something@VoxxedBucharest.pptxThe tests are trying to tell you something@VoxxedBucharest.pptx
The tests are trying to tell you something@VoxxedBucharest.pptx
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
PaLM Scaling Language Modeling with Pathways - 230219 (1).pdf
PaLM Scaling Language Modeling with Pathways - 230219 (1).pdfPaLM Scaling Language Modeling with Pathways - 230219 (1).pdf
PaLM Scaling Language Modeling with Pathways - 230219 (1).pdf
 
Context2Vec 기반 단어 의미 중의성 해소, Word Sense Disambiguation
Context2Vec 기반 단어 의미 중의성 해소, Word Sense DisambiguationContext2Vec 기반 단어 의미 중의성 해소, Word Sense Disambiguation
Context2Vec 기반 단어 의미 중의성 해소, Word Sense Disambiguation
 
Clean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a MonolithClean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a Monolith
 
Monadic Java
Monadic JavaMonadic Java
Monadic Java
 
20170227 파이썬으로 챗봇_만들기
20170227 파이썬으로 챗봇_만들기20170227 파이썬으로 챗봇_만들기
20170227 파이썬으로 챗봇_만들기
 
Open vocabulary problem
Open vocabulary problemOpen vocabulary problem
Open vocabulary problem
 
TDD (Test Driven Developement) et refactoring
TDD (Test Driven Developement) et refactoringTDD (Test Driven Developement) et refactoring
TDD (Test Driven Developement) et refactoring
 
Agile Test Driven Development
Agile Test Driven DevelopmentAgile Test Driven Development
Agile Test Driven Development
 
Design Patterns in React
Design Patterns in ReactDesign Patterns in React
Design Patterns in React
 
Groovy intro
Groovy introGroovy intro
Groovy intro
 
Agile Summit Taipei 2019 - Agile Testing Strategy
Agile Summit Taipei 2019 - Agile Testing StrategyAgile Summit Taipei 2019 - Agile Testing Strategy
Agile Summit Taipei 2019 - Agile Testing Strategy
 
Using OpenNLP with Solr to improve search relevance and to extract named enti...
Using OpenNLP with Solr to improve search relevance and to extract named enti...Using OpenNLP with Solr to improve search relevance and to extract named enti...
Using OpenNLP with Solr to improve search relevance and to extract named enti...
 
Introduction to GraphQL
Introduction to GraphQLIntroduction to GraphQL
Introduction to GraphQL
 

Ähnlich wie 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
 

Ähnlich wie 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
 

Kürzlich hochgeladen

CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Kürzlich hochgeladen (20)

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
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
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
 

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