{"id":130242,"date":"2025-01-30T18:04:00","date_gmt":"2025-01-30T16:04:00","guid":{"rendered":"https:\/\/www.javacodegeeks.com\/?p=130242"},"modified":"2025-01-24T11:05:50","modified_gmt":"2025-01-24T09:05:50","slug":"spring-data-jpa-query-with-arbitrary-and-clauses-example","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html","title":{"rendered":"Spring Data JPA Query With Arbitrary AND Clauses Example"},"content":{"rendered":"<p>Building dynamic queries is a common requirement in modern applications, especially when filtering data based on flexible and user-driven criteria. Spring Data JPA provides several mechanisms to achieve this, enabling us to construct queries dynamically without writing complex and repetitive SQL statements. In this article, we delve into three key approaches for creating dynamic queries in Spring Data JPA with arbitrary AND clauses: QueryDSL, Query by Example, and Query by Specification.<\/p>\n<h2 class=\"wp-block-heading\">1. Scenario<\/h2>\n<p>This guide demonstrates constructing dynamic queries using QueryDSL with two related entities in a one-to-many relationship. We will dynamically build queries based on arbitrary conditions to filter data across these entities. We will use the following entities:<\/p>\n<ul class=\"wp-block-list\">\n<li><code>Department<\/code>: Represents a company department.<\/li>\n<li><code>Employee<\/code>: Represents an employee belonging to a department (one <code>Department<\/code> can have many <code>Employees<\/code>).<\/li>\n<\/ul>\n<p>Users will query employees with filters on both <code>Employee<\/code> and <code>Department<\/code> fields.<\/p>\n<h2 class=\"wp-block-heading\">2. Setting Up QueryDSL in Your Project<\/h2>\n<p>To begin, we need to configure QueryDSL in our project. QueryDSL is a powerful library that allows us to build type-safe SQL-like queries using Java. It integrates smoothly with Spring Data JPA and supports dynamic query creation.<\/p>\n<p><strong>Maven Dependencies<\/strong><\/p>\n<p>Add the following dependencies to your <code>pom.xml<\/code> file:<\/p>\n<pre class=\"brush:xml\">\n    &lt;dependencies&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;com.querydsl&lt;\/groupId&gt;\n            &lt;artifactId&gt;querydsl-jpa&lt;\/artifactId&gt;\n            &lt;version&gt;5.1.0&lt;\/version&gt;\n            &lt;classifier&gt;jakarta&lt;\/classifier&gt;\n        &lt;\/dependency&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;com.querydsl&lt;\/groupId&gt;\n            &lt;artifactId&gt;querydsl-apt&lt;\/artifactId&gt;\n            &lt;version&gt;5.1.0&lt;\/version&gt;\n            &lt;classifier&gt;jakarta&lt;\/classifier&gt;\n            &lt;scope&gt;provided&lt;\/scope&gt;\n        &lt;\/dependency&gt;\n    &lt;\/dependencies&gt;\n\n\n&lt;build&gt;\n    &lt;plugins&gt;\n        &lt;plugin&gt;\n            &lt;groupId&gt;com.mysema.maven&lt;\/groupId&gt;\n            &lt;artifactId&gt;apt-maven-plugin&lt;\/artifactId&gt;\n            &lt;version&gt;1.1.3&lt;\/version&gt;\n            &lt;executions&gt;\n                &lt;execution&gt;\n\t\t    &lt;phase&gt;generate-sources&lt;\/phase&gt;\n                    &lt;goals&gt;\n                        &lt;goal&gt;process&lt;\/goal&gt;\n                    &lt;\/goals&gt;\n                    &lt;configuration&gt;\n                        &lt;outputDirectory&gt;target\/generated-sources&lt;\/outputDirectory&gt;\n                        &lt;processor&gt;com.querydsl.apt.jpa.JPAAnnotationProcessor&lt;\/processor&gt;\n                    &lt;\/configuration&gt;\n                &lt;\/execution&gt;\n            &lt;\/executions&gt;\n        &lt;\/plugin&gt;\n    &lt;\/plugins&gt;\n&lt;\/build&gt;\n<\/pre>\n<p>The first dependency here is <code>querydsl-jpa<\/code>. This is the core QueryDSL JPA module that provides support for building type-safe queries with JPA entities. The version <code>5.1.0<\/code> is specified, and the <code>jakarta<\/code> classifier ensures compatibility with the Jakarta Persistence API (<code>javax.persistence<\/code> was renamed to <code>jakarta.persistence<\/code> starting from Jakarta EE 9).<\/p>\n<p>The second dependency is <code>querydsl-apt<\/code>, which is responsible for generating the QueryDSL meta-classes (e.g., <code>QEmployee<\/code>, <code>QDepartment<\/code>) during the build process. The <code>scope<\/code> is set to <code>provided<\/code> because this dependency is needed only at compile time and doesn&#8217;t need to be included in the final packaged artifact. Like the previous dependency, it also uses the <code>jakarta<\/code> classifier to ensure compatibility with Jakarta Persistence.<\/p>\n<p><strong>Build Plugin<\/strong><\/p>\n<p>This plugin, <code>apt-maven-plugin<\/code>, is used to process annotations in the Java source code and generate additional classes. In this case, it generates the QueryDSL JPA meta-model classes from the JPA entities. The plugin&#8217;s version is <code>1.1.3<\/code>.<\/p>\n<p>The plugin is configured to run in the <code>generate-sources<\/code> phase of the Maven build lifecycle, ensuring that the meta-model classes are generated before compilation. The <code>goals<\/code> section specifies the <code>process<\/code> goal, which triggers annotation processing. The configuration includes:<\/p>\n<ul class=\"wp-block-list\">\n<li><strong><code>outputDirectory<\/code><\/strong>: Specifies where the generated source files should be placed, in this case, <code>target\/generated-sources<\/code>.<\/li>\n<li><strong><code>processor<\/code><\/strong>: Defines the annotation processor to use, which in this case is <code>com.querydsl.apt.jpa.JPAAnnotationProcessor<\/code>. This processor reads the JPA annotations from your entities and generates QueryDSL classes based on them.<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">3. Defining Entities<\/h2>\n<p>In our scenario, we have two entities: <code>Department<\/code> and <code>Employee<\/code>. A <code>Department<\/code> has many <code>Employees<\/code>, establishing a one-to-many relationship.<\/p>\n<p><strong>Department Entity<\/strong><\/p>\n<pre class=\"brush:java\">\n@Entity\npublic class Department {\n    @Id\n    @GeneratedValue(strategy = GenerationType.IDENTITY)\n    private Long id;\n\n    private String name;\n\n    @OneToMany(mappedBy = \"department\", cascade = CascadeType.ALL)\n    private List&lt;Employee&gt; employees;\n\n    \/\/ Getters and Setters\n}\n<\/pre>\n<p>The <code>Department<\/code> entity represents a company department. It includes:<\/p>\n<ul class=\"wp-block-list\">\n<li>A primary key <code>id<\/code>.<\/li>\n<li>A <code>name<\/code> field for the department name.<\/li>\n<li>A <code>List&lt;Employee&gt;<\/code> field annotated with <code>@OneToMany<\/code> to establish the <strong>one-to-many<\/strong> relationship. The <code>mappedBy<\/code> attribute indicates that the <code>department<\/code> field in the <code>Employee<\/code> entity owns the relationship.<\/li>\n<\/ul>\n<p><strong>Employee Entity<\/strong><\/p>\n<pre class=\"brush:java\">\n@Entity\npublic class Employee {\n    @Id\n    @GeneratedValue(strategy = GenerationType.IDENTITY)\n    private Long id;\n\n    private String firstName;\n    private String lastName;\n    private Integer age;\n\n    @ManyToOne\n    @JoinColumn(name = \"department_id\")\n    private Department department;\n\n    \/\/ Getters and Setters\n}\n<\/pre>\n<p>The <code>Employee<\/code> entity represents an employee within a department. It includes:<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<ul class=\"wp-block-list\">\n<li>A primary key <code>id<\/code>.<\/li>\n<li>Fields for <code>firstName<\/code>, <code>lastName<\/code>, and <code>age<\/code>.<\/li>\n<li>A <code>department<\/code> field annotated with <code>@ManyToOne<\/code> to establish the relationship back to the <code>Department<\/code> entity. The <code>@JoinColumn<\/code> annotation specifies the foreign key column as <code>department_id<\/code>.<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">4. Generating QueryDSL Meta-Model<\/h2>\n<p>After defining the entities, compile your project using Maven. QueryDSL will generate meta-model classes (<code>QEmployee<\/code> and <code>QDepartment<\/code>). These classes allow you to reference entity fields like <code>employee.firstName<\/code> or <code>department.name<\/code> in a type-safe manner when building queries.<\/p>\n<h3 class=\"wp-block-heading\">4.1 Using <code>QuerydslPredicateExecutor<\/code> for Simplified Dynamic Queries<\/h3>\n<p>A powerful feature of QueryDSL is its integration with Spring Data JPA through the <code>QuerydslPredicateExecutor<\/code> interface. This interface allows us to execute dynamic queries by combining predicates programmatically. In this section, we\u2019ll demonstrate how to apply <code>QuerydslPredicateExecutor<\/code> to the <code>Employee<\/code> and <code>Department<\/code> entities in our application.<\/p>\n<h4 class=\"wp-block-heading\">4.1.1 Defining the Employee Repository<\/h4>\n<p>To enable <code>QuerydslPredicateExecutor<\/code>, update the <code>EmployeeRepository<\/code> interface to extend it alongside <code>JpaRepository<\/code>. This provides built-in support for dynamic query execution using QueryDSL predicates.<\/p>\n<pre class=\"brush:java\">\npublic interface EmployeeRepository extends JpaRepository, QuerydslPredicateExecutor {\n\n}\n<\/pre>\n<p>The <code>JpaRepository&lt;Employee, Long&gt;<\/code> offers basic CRUD operations and pagination support for the <code>Employee<\/code> entity, while the <code>QuerydslPredicateExecutor&lt;Employee&gt;<\/code> allows the direct execution of QueryDSL predicates using the <code>findAll<\/code> method.<\/p>\n<h4 class=\"wp-block-heading\">4.1.2 Building and Executing Predicates<\/h4>\n<p>With the repository configured, we can now dynamically use QueryDSL to build predicates. Here\u2019s an example of querying employees who satisfy multiple criteria:<\/p>\n<pre class=\"brush:java\">\n@Service\npublic class EmployeeQueryService {\n\n    private final EmployeeRepository employeeRepository;\n\n    public EmployeeQueryService(EmployeeRepository employeeRepository) {\n        this.employeeRepository = employeeRepository;\n    }\n\n    public List&lt;Employee&gt; findEmployeesByMandatoryCriteria(String lastName, Integer age, String departmentName) {\n        QEmployee qEmployee = QEmployee.employee;\n\n        \/\/ Build the predicate with AND clauses\n        BooleanExpression predicate = qEmployee.lastName.endsWithIgnoreCase(lastName)\n            .and(qEmployee.age.eq(age))\n            .and(qEmployee.department.name.eq(departmentName));\n\n        \/\/ Execute the query and return results\n        return (List&lt;Employee&gt;) employeeRepository.findAll(predicate);\n    }\n}\n<\/pre>\n<p>This code defines a service class, <code>EmployeeQueryService<\/code>, which uses <a href=\"http:\/\/querydsl.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">QueryDSL<\/a> to construct dynamic queries for filtering employees based on various criteria. It demonstrates the flexibility of QueryDSL in building predicates dynamically and highlights the use of <code>.and()<\/code> clauses to combine multiple conditions logically.<\/p>\n<p>The above code dynamically constructs a query using QueryDSL predicates without any conditional checks. The <code>BooleanExpression<\/code> object <code>predicate<\/code> starts with the first condition, <code>qEmployee.lastName.endsWithIgnoreCase(lastName)<\/code>, filtering employees whose last name ends with the specified string (case-insensitive). Additional filters are appended to the predicate using the <code>.and()<\/code> method, which combines conditions logically to ensure all must be true. For example, the second condition <code>qEmployee.age.eq(age)<\/code> restricts the results to employees with an exact age match, while the third condition, <code>qEmployee.department.name.eq(departmentName)<\/code>, filters by department name.<\/p>\n<p>The <code>.and()<\/code> method plays a pivotal role by chaining these conditions into a single predicate, forming a cohesive query that can be executed in one call to the repository. By passing the combined predicate to the <code>findAll<\/code> method of <code>QuerydslPredicateExecutor<\/code>, the repository efficiently retrieves only those employees meeting all specified criteria. This code is ideal for scenarios where all filters are mandatory, eliminating the need for conditional checks. <\/p>\n<h3 class=\"wp-block-heading\">4.2 Exposing the Service through a REST Endpoint<\/h3>\n<p>To make this query accessible, you can expose it through a REST controller:<\/p>\n<pre class=\"brush:java\">\n@RestController\npublic class EmployeeController {\n\n    private final EmployeeQueryService employeeQueryService;\n\n    public EmployeeController(EmployeeQueryService employeeQueryService) {\n        this.employeeQueryService = employeeQueryService;\n    }\n\n    @GetMapping(\"\/employees\")\n    public List&lt;Employee&gt; getEmployees(\n            @RequestParam String lastName,\n            @RequestParam Integer age,\n            @RequestParam String departmentName) {\n        return employeeQueryService.findEmployeesByMandatoryCriteria(lastName, age, departmentName);\n    }\n}\n\n<\/pre>\n<p>The code below shows how to add sample data to the database for testing the endpoint:<\/p>\n<pre class=\"brush:java\">\n@SpringBootApplication\npublic class DynamicJpaQuerydslApplication implements CommandLineRunner {\n\n    private final EmployeeRepository employeeRepository;\n    private final DepartmentRepository departmentRepository;\n\n    public DynamicJpaQuerydslApplication(EmployeeRepository employeeRepository, DepartmentRepository departmentRepository) {\n        this.employeeRepository = employeeRepository;\n        this.departmentRepository = departmentRepository;\n    }\n\n    public static void main(String[] args) {\n        SpringApplication.run(DynamicJpaQuerydslApplication.class, args);\n    }\n\n    @Override\n    public void run(String... args) {\n\n        Department sales = new Department(1L, \"Sales\", null);\n        Department marketing = new Department(2L, \"Marketing\", null);\n\n        departmentRepository.save(sales);\n        departmentRepository.save(marketing);\n\n        Employee johnSmith = new Employee(1L, \"Thomas\", \"Smith\", 25, sales);\n        Employee aliceJohnson = new Employee(2L, \"Alice\", \"Franklin\", 30, marketing);\n        Employee bobSmith = new Employee(3L, \"Bob\", \"Fish\", 25, sales);\n\n        employeeRepository.save(johnSmith);\n        employeeRepository.save(aliceJohnson);\n        employeeRepository.save(bobSmith);\n\n    }\n\n}\n\n<\/pre>\n<h3 class=\"wp-block-heading\">4.3 Testing the Endpoint<\/h3>\n<p>Once the application is running, we can test the endpoint using a tool like Postman or a browser. For example, the following request on a browser (<code>http:\/\/localhost:8080\/employees?lastName=Smith&amp;age=25&amp;departmentName=Sales<\/code>) retrieves employees matching the criteria:<\/p>\n<p><strong>Response<\/strong> (JSON):<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2025\/01\/querydsltest.png\"><img decoding=\"async\" width=\"710\" height=\"216\" src=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2025\/01\/querydsltest.png\" alt=\"Screenshot of browser output for a Spring Data JPA query with arbitrary AND clauses example.\" class=\"wp-image-130685\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2025\/01\/querydsltest.png 710w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2025\/01\/querydsltest-300x91.png 300w\" sizes=\"(max-width: 710px) 100vw, 710px\" \/><\/a><\/figure>\n<\/div>\n<h2 class=\"wp-block-heading\">5. Query by Example (QBE)<\/h2>\n<p>Spring Data JPA supports <a href=\"https:\/\/docs.spring.io\/spring-data\/jpa\/reference\/repositories\/query-by-example.html\" target=\"_blank\" rel=\"noreferrer noopener\">Query by Example<\/a><strong> (QBE)<\/strong>, allowing us to dynamically construct queries based on a sample entity (example). This is particularly useful for building filters without explicitly writing queries. To support Query by Example, the repository interface must extend both <code>JpaRepository<\/code> and <code>QueryByExampleExecutor<\/code>. <\/p>\n<p>Here is how we can integrate QBE into the application:<\/p>\n<pre class=\"brush:java\">\npublic interface EmployeeRepository extends JpaRepository&lt;Employee, Long&gt;, QueryByExampleExecutor&lt;Employee&gt; {\n}\n<\/pre>\n<p><strong>Implement the Service Layer<\/strong><\/p>\n<pre class=\"brush:java\">\n@Service\npublic class EmployeeQueryByExampleService {\n\n    @Autowired\n    EmployeeRepository employeeRepository;\n\n    public List&lt;Employee&gt; findEmployeesByExample(String lastName, Integer age, String departmentName) {\n        \n        Employee probe = new Employee();\n        probe.setLastName(lastName);\n        probe.setAge(age);\n\n        Department department = new Department();\n        department.setName(departmentName);\n        probe.setDepartment(department);\n\n        \/\/ Create an Example with matching rules\n        ExampleMatcher matcher = ExampleMatcher.matching()\n                .withIgnorePaths(\"id\") \/\/ Ignore ID field\n                .withIgnoreNullValues() \/\/ Ignore null values\n                .withStringMatcher(ExampleMatcher.StringMatcher.ENDING); \/\/ Match strings by ending\n\n        Example&lt;Employee&gt; example = Example.of(probe, matcher);\n\n        return employeeRepository.findAll(example);\n    }\n}\n\n<\/pre>\n<p>Query by Example works by creating a probe, which is a sample entity with fields set to the desired query values. An <code>ExampleMatcher<\/code> is used to define matching rules, such as ignoring null values and specifying how string comparisons are handled. The probe and matcher are combined into an <code>Example<\/code> object, which serves as a query definition. This <code>Example<\/code> is then passed to the <code>findAll<\/code> method, allowing dynamic query execution without the need to write explicit SQL.<\/p>\n<h2 class=\"wp-block-heading\">6. Query by Specification<\/h2>\n<p>Spring Data JPA also supports Specifications, a more advanced and flexible way to build dynamic queries programmatically using the <code>Specification<\/code> interface. To enable Specifications, update the repository by extending the interface with <code>JpaSpecificationExecutor<\/code> in addition to <code>JpaRepository<\/code> to support building and executing Specifications. This enables dynamic query construction based on flexible criteria.<\/p>\n<p>Update the Repository and add <code>JpaSpecificationExecutor<\/code> to the repository to enable Specifications.<\/p>\n<pre class=\"brush:java\">\npublic interface EmployeeRepository extends JpaRepository&lt;Employee, Long&gt;, JpaSpecificationExecutor&lt;Employee&gt; {\n}\n<\/pre>\n<p>Next, create a custom <code>Specification<\/code> class for building predicates dynamically.<\/p>\n<pre class=\"brush:java\">\npublic class EmployeeSpecifications {\n\n    public static Specification&lt;Employee&gt; hasLastName(String lastName) {\n        return (root, query, criteriaBuilder) -&gt;\n                criteriaBuilder.like(root.get(\"lastName\"), \"%\" + lastName);\n    }\n\n    public static Specification&lt;Employee&gt; hasAge(Integer age) {\n        return (root, query, criteriaBuilder) -&gt;\n                criteriaBuilder.equal(root.get(\"age\"), age);\n    }\n\n    public static Specification&lt;Employee&gt; hasDepartmentName(String departmentName) {\n        return (root, query, criteriaBuilder) -&gt;\n                criteriaBuilder.equal(root.join(\"department\").get(\"name\"), departmentName);\n    }\n}\n\n<\/pre>\n<p>The <code>EmployeeSpecifications<\/code> class provides reusable methods to build dynamic query predicates using Spring Data JPA&#8217;s <code>Specification<\/code> interface and the <code>CriteriaBuilder<\/code>. The <code>hasLastName<\/code> method uses <code>criteriaBuilder.like<\/code> to generate a predicate for matching employee last names with a wildcard pattern. The <code>hasAge<\/code> method leverages <code>criteriaBuilder.equal<\/code> to create a condition for exact age matching. Similarly, the <code>hasDepartmentName<\/code> method uses <code>criteriaBuilder.equal<\/code> in conjunction with <code>root.join<\/code> to filter employees based on their department name by performing a join between the <code>Employee<\/code> and <code>Department<\/code> entities. Each method dynamically constructs criteria for flexible query building.<\/p>\n<p>Next, Use the <code>Specification<\/code> class to combine multiple dynamic conditions with <code>.and()<\/code> or <code>.or()<\/code> like this:<\/p>\n<pre class=\"brush:java\">\n@Service\npublic class EmployeeQueryBySpecificationService {\n    \n    @Autowired\n    EmployeeRepository employeeRepository;\n    \n    public List&lt;Employee&gt; findEmployeesBySpecification(String lastName, Integer age, String departmentName) {\n        Specification&lt;Employee&gt; spec = Specification.where(null);\n\n        \/\/ Add dynamic specifications\n        spec = spec.and(EmployeeSpecifications.hasLastName(lastName));\n        spec = spec.and(EmployeeSpecifications.hasAge(age));\n        spec = spec.and(EmployeeSpecifications.hasDepartmentName(departmentName));\n\n        return employeeRepository.findAll(spec);\n    }\n}\n\n<\/pre>\n<p>These two approaches &#8211; <strong>Query by Example<\/strong> and <strong>Query by Specification<\/strong>, offer alternatives to dynamic query building, complementing QueryDSL for different use cases in our Spring Data JPA application.<\/p>\n<h2 class=\"wp-block-heading\">7. Conclusion<\/h2>\n<p>In this article, we explored dynamic query building in Spring Data JPA using a variety of approaches, including QueryDSL, Query by Example, and Query by Specification. Each method provides a unique and effective way to construct queries dynamically, catering to different use cases. We demonstrated how to use the <code>.and<\/code> operator in QueryDSL for combining multiple conditions seamlessly, enabling type-safe and expressive queries. Similarly, Query by Example and Query by Specification offer declarative and reusable ways to build complex filtering criteria without writing explicit SQL.<\/p>\n<h2 class=\"wp-block-heading\">8. Download the Source Code<\/h2>\n<p>This article focused on building a Spring Data JPA query with arbitrary AND clauses for dynamic and flexible filtering.<\/p>\n<div class=\"download\"><strong>Download<\/strong><br \/>\nYou can download the full source code of this example here: <a href=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2025\/01\/dynamic-jpa-querydsl.zip\"><strong>spring data jpa query arbitrary and clauses<\/strong><\/a>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Building dynamic queries is a common requirement in modern applications, especially when filtering data based on flexible and user-driven criteria. Spring Data JPA provides several mechanisms to achieve this, enabling us to construct queries dynamically without writing complex and repetitive SQL statements. In this article, we delve into three key approaches for creating dynamic queries &hellip;<\/p>\n","protected":false},"author":128888,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[33,321],"class_list":["post-130242","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-jpa","tag-spring-data"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Spring Data JPA Query With Arbitrary AND Clauses Example - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Learn how to build a dynamic Spring Data JPA query with arbitrary AND clauses using QueryDSL for flexible and efficient filtering.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring Data JPA Query With Arbitrary AND Clauses Example - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Learn how to build a dynamic Spring Data JPA query with arbitrary AND clauses using QueryDSL for flexible and efficient filtering.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:author\" content=\"https:\/\/web.facebook.com\/omos.aziegbe\" \/>\n<meta property=\"article:published_time\" content=\"2025-01-30T16:04:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Omozegie Aziegbe\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/OAziegbe\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Omozegie Aziegbe\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html\"},\"author\":{\"name\":\"Omozegie Aziegbe\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/7d3eac6e45542536e961129ae0fb453e\"},\"headline\":\"Spring Data JPA Query With Arbitrary AND Clauses Example\",\"datePublished\":\"2025-01-30T16:04:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html\"},\"wordCount\":1365,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"JPA\",\"Spring Data\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html\",\"name\":\"Spring Data JPA Query With Arbitrary AND Clauses Example - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2025-01-30T16:04:00+00:00\",\"description\":\"Learn how to build a dynamic Spring Data JPA query with arbitrary AND clauses using QueryDSL for flexible and efficient filtering.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"spring-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Spring Data JPA Query With Arbitrary AND Clauses Example\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/7d3eac6e45542536e961129ae0fb453e\",\"name\":\"Omozegie Aziegbe\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2023\\\/12\\\/cropped-jcg_profile_pic-96x96.jpg\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2023\\\/12\\\/cropped-jcg_profile_pic-96x96.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2023\\\/12\\\/cropped-jcg_profile_pic-96x96.jpg\",\"caption\":\"Omozegie Aziegbe\"},\"description\":\"Omos Aziegbe is a technical writer and web\\\/application developer with a BSc in Computer Science and Software Engineering from the University of Bedfordshire. Specializing in Java enterprise applications with the Jakarta EE framework, Omos also works with HTML5, CSS, and JavaScript for web development. As a freelance web developer, Omos combines technical expertise with research and writing on topics such as software engineering, programming, web application development, computer science, and technology.\",\"sameAs\":[\"https:\\\/\\\/web.facebook.com\\\/omos.aziegbe\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/omosaziegbe\\\/\",\"https:\\\/\\\/x.com\\\/https:\\\/\\\/twitter.com\\\/OAziegbe\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/omozegie-aziegbe\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Spring Data JPA Query With Arbitrary AND Clauses Example - Java Code Geeks","description":"Learn how to build a dynamic Spring Data JPA query with arbitrary AND clauses using QueryDSL for flexible and efficient filtering.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html","og_locale":"en_US","og_type":"article","og_title":"Spring Data JPA Query With Arbitrary AND Clauses Example - Java Code Geeks","og_description":"Learn how to build a dynamic Spring Data JPA query with arbitrary AND clauses using QueryDSL for flexible and efficient filtering.","og_url":"https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_author":"https:\/\/web.facebook.com\/omos.aziegbe","article_published_time":"2025-01-30T16:04:00+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","type":"image\/jpeg"}],"author":"Omozegie Aziegbe","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/OAziegbe","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Omozegie Aziegbe","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html"},"author":{"name":"Omozegie Aziegbe","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/7d3eac6e45542536e961129ae0fb453e"},"headline":"Spring Data JPA Query With Arbitrary AND Clauses Example","datePublished":"2025-01-30T16:04:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html"},"wordCount":1365,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["JPA","Spring Data"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html","url":"https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html","name":"Spring Data JPA Query With Arbitrary AND Clauses Example - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2025-01-30T16:04:00+00:00","description":"Learn how to build a dynamic Spring Data JPA query with arbitrary AND clauses using QueryDSL for flexible and efficient filtering.","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","width":150,"height":150,"caption":"spring-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/spring-data-jpa-query-with-arbitrary-and-clauses-example.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Spring Data JPA Query With Arbitrary AND Clauses Example"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/7d3eac6e45542536e961129ae0fb453e","name":"Omozegie Aziegbe","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2023\/12\/cropped-jcg_profile_pic-96x96.jpg","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2023\/12\/cropped-jcg_profile_pic-96x96.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2023\/12\/cropped-jcg_profile_pic-96x96.jpg","caption":"Omozegie Aziegbe"},"description":"Omos Aziegbe is a technical writer and web\/application developer with a BSc in Computer Science and Software Engineering from the University of Bedfordshire. Specializing in Java enterprise applications with the Jakarta EE framework, Omos also works with HTML5, CSS, and JavaScript for web development. As a freelance web developer, Omos combines technical expertise with research and writing on topics such as software engineering, programming, web application development, computer science, and technology.","sameAs":["https:\/\/web.facebook.com\/omos.aziegbe","https:\/\/www.linkedin.com\/in\/omosaziegbe\/","https:\/\/x.com\/https:\/\/twitter.com\/OAziegbe"],"url":"https:\/\/www.javacodegeeks.com\/author\/omozegie-aziegbe"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/130242","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/128888"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=130242"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/130242\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=130242"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=130242"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=130242"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}