diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000000..5c28208220 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,47 @@ +name: Deploy Documentation + +on: + push: + branches: ["master"] + paths: + - "docs/**" + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Pages + uses: actions/configure-pages@v5 + + - name: Build with Jekyll + uses: actions/jekyll-build-pages@v1 + with: + source: ./docs + destination: ./_site + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..f9367f10cd --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,77 @@ +# Contributing to Querydsl + +GitHub pull requests are the way to contribute to Querydsl. + +## Documentation + +The documentation site is built with [Jekyll](https://jekyllrb.com/) using the +[just-the-docs](https://just-the-docs.com/) theme and hosted on GitHub Pages. + +Source files live in the `docs/` directory. Changes to `docs/**` on the +`master` branch automatically trigger a rebuild and deploy. + +### Editing Documentation + +1. Fork the repository and create a branch from `master`. +2. Edit or add Markdown files under `docs/`. +3. Use Liquid variables for version and groupId: + - `{{ site.querydsl_version }}` — current release version + - `{{ site.group_id }}` — Maven groupId +4. Open a pull request. + +### Local Preview + +To preview the site locally: + +```bash +cd docs +bundle install +bundle exec jekyll serve +``` + +Then open `http://localhost:4000/querydsl/` in your browser. + +### Structure + +``` +docs/ +├── _config.yml # Jekyll configuration and variables +├── Gemfile # Ruby dependencies +├── index.md # Landing page +├── introduction.md # Background and principles +├── tutorials/ # Backend-specific tutorials +├── guides/ # Cross-cutting guides +├── troubleshooting.md # Common issues +└── migration.md # Migration from upstream querydsl +``` + +## Code Contributions + +### Building + +```bash +./mvnw -Pquickbuild clean install +``` + +### Running Tests + +```bash +# Without external databases +./mvnw -Pdev verify + +# CI profile +./mvnw -Pci verify +``` + +### Code Formatting + +```bash +./mvnw -Pdev initialize +``` + +### Pull Request Process + +1. Fork the repository and create a feature branch. +2. Make your changes and add tests where appropriate. +3. Run `./mvnw -Pdev verify` to make sure tests pass. +4. Open a pull request against `master`. diff --git a/README.md b/README.md index 9fafb5e5e7..288f68a088 100644 --- a/README.md +++ b/README.md @@ -42,17 +42,23 @@ Get a querydsl project active! May be as a fork, may be as a wake up call to pr Well, you will need to get your hands dirty. I might fix bugs or create features, but mostly when they affect my day job. Sorry, just a single guy here doing free work on spare time. +**Documentation** + +Full reference documentation is available at **[openfeign.github.io/querydsl](https://openfeign.github.io/querydsl)**. + **Getting started** Use these tutorials to get started -* [Querying JPA](http://www.querydsl.com/static/querydsl/latest/reference/html/ch02.html#jpa_integration) -* [Querying SQL](http://www.querydsl.com/static/querydsl/latest/reference/html/ch02s03.html) -* [Querying Mongodb](http://www.querydsl.com/static/querydsl/latest/reference/html/ch02s07.html) -* [Querying Lucene](http://www.querydsl.com/static/querydsl/latest/reference/html/ch02s05.html) -* [Querying Collections](http://www.querydsl.com/static/querydsl/latest/reference/html/ch02s08.html) -* [Querydsl Spatial](http://www.querydsl.com/static/querydsl/latest/reference/html/ch02s04.html) -* [Querying JDO](http://www.querydsl.com/static/querydsl/latest/reference/html/ch02s02.html) +* [Querying JPA](https://openfeign.github.io/querydsl/tutorials/jpa) +* [Querying SQL](https://openfeign.github.io/querydsl/tutorials/sql) +* [Querying R2DBC](https://openfeign.github.io/querydsl/tutorials/r2dbc) +* [Querying MongoDB](https://openfeign.github.io/querydsl/tutorials/mongodb) +* [Querying Collections](https://openfeign.github.io/querydsl/tutorials/collections) +* [Querydsl Spatial](https://openfeign.github.io/querydsl/tutorials/spatial) +* [Querying in Kotlin](https://openfeign.github.io/querydsl/tutorials/kotlin) +* [Querying in Scala](https://openfeign.github.io/querydsl/tutorials/scala) +* [Migration Guide](https://openfeign.github.io/querydsl/migration) **Examples** @@ -72,7 +78,7 @@ $ mvn -Pquickbuild,{projectname} clean install ``` Where projectname is one of the Maven profiles (e.g. `jpa`, `sql`, `mongodb`, etc. or `all`) -For more information visit the project homepage at https://querydsl.github.io. +For more information visit the [documentation site](https://openfeign.github.io/querydsl). **Docker Compose setup** diff --git a/dist.sh b/dist.sh index 0dead02a00..60523587fc 100755 --- a/dist.sh +++ b/dist.sh @@ -8,6 +8,3 @@ do mvn -pl querydsl-$module -Dtest=X clean assembly:assembly done -mkdir -p target/dist/reference -mvn -f querydsl-docs/pom.xml -Dxslthl.config=http://docbook.sourceforge.net/release/xsl/current/highlighting/xslthl-config.xml clean package -cp -R querydsl-docs/target/docbook/publish/en-US/* target/dist/reference/ diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000000..7ece0c2482 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,3 @@ +_site/ +.jekyll-cache/ +Gemfile.lock diff --git a/docs/Gemfile b/docs/Gemfile new file mode 100644 index 0000000000..102260a180 --- /dev/null +++ b/docs/Gemfile @@ -0,0 +1,10 @@ +source "https://rubygems.org" + +gem "jekyll", "~> 4.3" +gem "just-the-docs", "~> 0.10" +gem "jekyll-remote-theme" + +group :jekyll_plugins do + gem "jekyll-seo-tag" + gem "jekyll-include-cache" +end diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000000..9b5f220f46 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1,62 @@ +title: Querydsl +description: >- + Type-safe SQL-like queries for Java — JPA, SQL, MongoDB, R2DBC, Collections, and more. +url: "https://openfeign.github.io" +baseurl: "/querydsl" + +remote_theme: just-the-docs/just-the-docs@v0.10.0 + +querydsl_version: "7.1" +group_id: "io.github.openfeign.querydsl" + +permalink: pretty + +exclude: + - Gemfile + - Gemfile.lock + - node_modules + - vendor + +search_enabled: true + +heading_anchors: true + +nav_enabled: true + +back_to_top: true +back_to_top_text: "Back to top" + +aux_links: + GitHub: + - "https://github.com/OpenFeign/querydsl" + Maven Central: + - "https://central.sonatype.com/namespace/io.github.openfeign.querydsl" + +aux_links_new_tab: true + +gh_edit_link: true +gh_edit_link_text: "Edit this page on GitHub" +gh_edit_repository: "https://github.com/OpenFeign/querydsl" +gh_edit_branch: "master" +gh_edit_source: "docs" +gh_edit_view_mode: "edit" + +footer_content: >- + Copyright © 2007–2026 Querydsl team. Maintained by the + OpenFeign community. + Distributed under the + Apache License 2.0. + +last_edit_timestamp: true +last_edit_time_format: "%b %e %Y at %I:%M %p" + +callouts: + warning: + title: Warning + color: red + note: + title: Note + color: blue + tip: + title: Tip + color: green diff --git a/querydsl-docs/src/main/docbook/media/spatial.svg b/docs/assets/images/spatial.svg similarity index 100% rename from querydsl-docs/src/main/docbook/media/spatial.svg rename to docs/assets/images/spatial.svg diff --git a/docs/guides/alias-usage.md b/docs/guides/alias-usage.md new file mode 100644 index 0000000000..e221c6f944 --- /dev/null +++ b/docs/guides/alias-usage.md @@ -0,0 +1,78 @@ +--- +layout: default +title: Alias Usage +parent: Guides +nav_order: 4 +--- + +# Alias Usage + +In cases where code generation is not an option, alias objects can be used as +path references for expression construction. They work via proxied Java Bean +objects through getter method invocations. + +The following examples demonstrate how alias objects can be used as +replacements for expression creation based on generated types. + +First, an example query with APT-generated domain types: + +```java +QCat cat = new QCat("cat"); +for (String name : queryFactory.select(cat.name).from(cat,cats) + .where(cat.kittens.size().gt(0)) + .fetch()) { + System.out.println(name); +} +``` + +And now with an alias instance for the `Cat` class. The call +`c.getKittens()` inside the dollar-method is internally transformed into the +property path `c.kittens`. + +```java +Cat c = alias(Cat.class, "cat"); +for (String name : select($(c.getName())).from($(c),cats) + .where($(c.getKittens()).size().gt(0)) + .fetch()) { + System.out.println(name); +} +``` + +To use the alias functionality, add the following two imports: + +```java +import static com.querydsl.core.alias.Alias.$; +import static com.querydsl.core.alias.Alias.alias; +``` + +The following example is a variation where the access to the list size happens +inside the dollar-method invocation: + +```java +Cat c = alias(Cat.class, "cat"); +for (String name : queryFactory.select($(c.getName())).from($(c),cats) + .where($(c.getKittens().size()).gt(0)) + .fetch()) { + System.out.println(name); +} +``` + +All non-primitive and non-final typed properties of aliases are aliases +themselves. You may cascade method calls until you hit a primitive or final +type in the dollar-method scope, e.g.: + +```java +$(c.getMate().getName()) +``` + +is transformed into `c.mate.name` internally, but: + +```java +$(c.getMate().getName().toLowerCase()) +``` + +is not transformed properly, since the `toLowerCase()` invocation is not +tracked. + +You may only invoke getters, `size()`, `contains(Object)`, and `get(int)` on +alias types. All other invocations throw exceptions. diff --git a/docs/guides/code-generation.md b/docs/guides/code-generation.md new file mode 100644 index 0000000000..12f8ae8621 --- /dev/null +++ b/docs/guides/code-generation.md @@ -0,0 +1,393 @@ +--- +layout: default +title: Code Generation +parent: Guides +nav_order: 3 +--- + +# Code Generation + +Querydsl uses Java annotation processing (APT) for code generation in the JPA +and MongoDB modules. This section describes various configuration options for +the code generation and alternatives to APT usage. + +## Path Initialization + +By default, Querydsl initializes only reference properties of the first two +levels. When longer initialization paths are required, annotate the domain +types with `com.querydsl.core.annotations.QueryInit`: + +```java +@Entity +class Event { + @QueryInit("customer.address") + Account account; +} + +@Entity +class Account { + Customer customer; +} + +@Entity +class Customer { + String name; + Address address; + // ... +} +``` + +This enforces the initialization of the `account.customer` path when an +`Event` path is initialized as a root path / variable. The path initialization +format supports wildcards as well, e.g. `"customer.*"` or just `"*"`. + +The automatic path initialization replaces the manual one, which required the +entity fields to be non-final. The declarative format has the benefit of being +applied to all top-level instances of a query type and enabling the usage of +final entity fields. + +Automatic path initialization is the preferred initialization strategy, but +manual initialization can be activated via the `@Config` annotation. + +## Customization + +The serialization of Querydsl can be customized via `@Config` annotations on +packages and types. + +### Config Options + +| Name | Description | +|:-----|:------------| +| `entityAccessors` | Accessor methods for entity paths instead of public final fields (default: `false`) | +| `listAccessors` | `listProperty(int index)` style methods (default: `false`) | +| `mapAccessors` | `mapProperty(Key key)` style accessor methods (default: `false`) | +| `createDefaultVariable` | Generate the default variable (default: `true`) | +| `defaultVariableName` | Name of the default variable | + +Examples: + +Customization of entity type serialization: + +```java +@Config(entityAccessors=true) +@Entity +public class User { + //... +} +``` + +Customization of package content: + +```java +@Config(listAccessors=true) +package com.querydsl.core.domain.rel; + +import com.querydsl.core.annotations.Config; +``` + +### APT Options + +To customize the serializer configuration globally, use the following APT +options: + +| Name | Description | +|:-----|:------------| +| `querydsl.entityAccessors` | Enable reference field accessors | +| `querydsl.listAccessors` | Enable accessors for direct indexed list access | +| `querydsl.mapAccessors` | Enable accessors for direct key-based map access | +| `querydsl.prefix` | Override the prefix for query types (default: `Q`) | +| `querydsl.suffix` | Set a suffix for query types | +| `querydsl.packageSuffix` | Set a suffix for query type packages | +| `querydsl.createDefaultVariable` | Set whether default variables are created | +| `querydsl.unknownAsEmbeddable` | Set whether unknown non-annotated classes should be treated as embeddable (default: `false`) | +| `querydsl.includedPackages` | Comma-separated list of packages to include into code generation (default: all) | +| `querydsl.includedClasses` | Comma-separated list of class names to include into code generation (default: all) | +| `querydsl.excludedPackages` | Comma-separated list of packages to exclude from code generation (default: none) | +| `querydsl.excludedClasses` | Comma-separated list of class names to exclude from code generation (default: none) | +| `querydsl.useFields` | Set whether fields are used as metadata source (default: `true`) | +| `querydsl.useGetters` | Set whether accessors are used as metadata source (default: `true`) | +| `querydsl.generatedAnnotationClass` | Fully qualified class name of the annotation to add on generated sources | + +### Using maven-compiler-plugin + +The recommended approach is to configure `maven-compiler-plugin` to hook APT +directly into compilation: + +```xml + + maven-compiler-plugin + + target/generated-sources/java + + -Aquerydsl.entityAccessors=true + -Aquerydsl.useFields=false + + + + + {{ site.group_id }} + querydsl-apt + {{ site.querydsl_version }} + jpa + + + jakarta.persistence + jakarta.persistence-api + 3.1.0 + + + +``` + +You need to use a proper classifier when defining the dependency on +`{{ site.group_id }}:querydsl-apt`. The additional artifacts define the +annotation processor to be used in +`META-INF/services/javax.annotation.processing.Processor`. + +Available classifiers: + +- `general` +- `hibernate` +- `jpa` + +With this configuration, query objects have their sources generated and +compiled during compilation of the domain objects. This also automatically +adds the generated sources directory to Maven project source roots. + +## Custom Type Mappings + +Custom type mappings can be used on properties to override the derived `Path` +type. This is useful in cases where comparison and String operations should be +blocked on certain String paths, or Date/Time support for custom types needs +to be added. + +Support for Date/Time types of the Joda time API and JDK (`java.util.Date`, +`Calendar` and subtypes) is built in, but other APIs might need to be +supported using this feature. + +```java +@Entity +public class MyEntity { + @QueryType(PropertyType.SIMPLE) + public String stringAsSimple; + + @QueryType(PropertyType.COMPARABLE) + public String stringAsComparable; + + @QueryType(PropertyType.NONE) + public String stringNotInQuerydsl; +} +``` + +The value `PropertyType.NONE` can be used to skip a property in query type +generation. This is different from `@Transient` or `@QueryTransient` +annotated properties, where properties are not persisted. `PropertyType.NONE` +just omits the property from the Querydsl query type. + +## Delegate Methods + +To declare a static method as a delegate method, add the `@QueryDelegate` +annotation with the corresponding domain type as a value and provide a method +signature that takes the corresponding Querydsl query type as the first +argument. + +```java +@QueryEntity +public static class User { + String name; + User manager; +} +``` + +```java +@QueryDelegate(User.class) +public static BooleanPath isManagedBy(QUser user, User other) { + return user.manager.eq(other); +} +``` + +The generated method in the `QUser` query type: + +```java +public BooleanPath isManagedBy(QUser other) { + return DelegateTest.isManagedBy(this, other); +} +``` + +Delegate methods can also extend built-in types: + +```java +public class QueryExtensions { + + @QueryDelegate(Date.class) + public static BooleanExpression inPeriod(DatePath date, Pair period) { + return date.goe(period.getFirst()).and(date.loe(period.getSecond())); + } + + @QueryDelegate(Timestamp.class) + public static BooleanExpression inDatePeriod(DateTimePath timestamp, Pair period) { + Timestamp first = new Timestamp(DateUtils.truncate(period.getFirst(), Calendar.DAY_OF_MONTH).getTime()); + Calendar second = Calendar.getInstance(); + second.setTime(DateUtils.truncate(period.getSecond(), Calendar.DAY_OF_MONTH)); + second.add(1, Calendar.DAY_OF_MONTH); + return timestamp.goe(first).and(timestamp.lt(new Timestamp(second.getTimeInMillis()))); + } +} +``` + +When delegate methods are declared for built-in types, subclasses with the +proper delegate method usages are created. + +## Non-annotated Types + +It is possible to create Querydsl query types for non-annotated types by +creating `@QueryEntities` annotations. Place a `@QueryEntities` annotation +into a package of your choice and the classes to mirror in the value attribute. + +To create the types, use the `com.querydsl.apt.QuerydslAnnotationProcessor`. +In Maven, configure the `maven-compiler-plugin`: + +```xml + + maven-compiler-plugin + + target/generated-sources/java + + + + {{ site.group_id }} + querydsl-apt + {{ site.querydsl_version }} + general + + + +``` + +## Classpath-based Code Generation + +For cases where annotated Java sources are not available, such as the usage of +a different JVM language (Scala, Groovy) or annotation addition via bytecode +manipulation, the `GenericExporter` class can be used to scan the classpath +for annotated classes and generate query types. + +Add a dependency to the `querydsl-codegen` module: + +```xml + + {{ site.group_id }} + querydsl-codegen + {{ site.querydsl_version }} + +``` + +Example for JPA: + +```java +GenericExporter exporter = new GenericExporter(); +exporter.setKeywords(Keywords.JPA); +exporter.setEntityAnnotation(Entity.class); +exporter.setEmbeddableAnnotation(Embeddable.class); +exporter.setEmbeddedAnnotation(Embedded.class); +exporter.setSupertypeAnnotation(MappedSuperclass.class); +exporter.setSkipAnnotation(Transient.class); +exporter.setTargetFolder(new File("target/generated-sources/java")); +exporter.export(DomainClass.class.getPackage()); +``` + +This exports all JPA-annotated classes in the package of `DomainClass` and +subpackages to the `target/generated-sources/java` directory. + +### Usage via Maven + +The goals `generic-export`, `jpa-export`, and `jdo-export` of the +`querydsl-maven-plugin` can be used for `GenericExporter` usage via Maven. + +| Type | Element | Description | +|:-----|:--------|:------------| +| `File` | `targetFolder` | Target folder for generated sources | +| `boolean` | `scala` | `true` if Scala sources should be generated instead (default: `false`) | +| `String[]` | `packages` | Packages to be introspected for entity classes | +| `boolean` | `handleFields` | `true` if fields should be treated as properties (default: `true`) | +| `boolean` | `handleMethods` | `true` if getters should be treated as properties (default: `true`) | +| `String` | `sourceEncoding` | Charset encoding for generated source files | +| `boolean` | `testClasspath` | `true` if the test classpath should be used instead | + +Example for JPA annotated classes: + +```xml + + {{ site.group_id }} + querydsl-maven-plugin + {{ site.querydsl_version }} + + + process-classes + + jpa-export + + + target/generated-sources/java + + com.example.domain + + + + + +``` + +This exports the JPA-annotated classes of the `com.example.domain` package and +subpackages to the `target/generated-sources/java` directory. + +If you need to compile the generated sources directly after that, use the +`compile` goal: + +```xml + + + compile + + + target/generated-sources/java + + +``` + +### Scala Support + +For Scala output, use a variant of the following configuration: + +```xml + + {{ site.group_id }} + querydsl-maven-plugin + {{ site.querydsl_version }} + + + {{ site.group_id }} + querydsl-scala + {{ site.querydsl_version }} + + + org.scala-lang + scala-library + ${scala.version} + + + + + + jpa-export + + + target/generated-sources/scala + true + + com.example.domain + + + + + +``` diff --git a/docs/guides/creating-queries.md b/docs/guides/creating-queries.md new file mode 100644 index 0000000000..90777d5bab --- /dev/null +++ b/docs/guides/creating-queries.md @@ -0,0 +1,201 @@ +--- +layout: default +title: Creating Queries +parent: Guides +nav_order: 1 +--- + +# Creating Queries + +Query construction in Querydsl involves calling query methods with expression +arguments. Since query methods are mostly module-specific and have already been +presented in the tutorial section, this part focuses on expressions. + +Expressions are normally constructed by accessing fields and calling methods on +the generated expression types of your domain module. For cases where code +generation is not applicable, generic ways to construct expressions can be used +instead. + +## Complex Predicates + +To construct complex boolean expressions, use the +`com.querydsl.core.BooleanBuilder` class. It implements `Predicate` and can be +used in cascaded form: + +```java +public List getCustomer(String... names) { + QCustomer customer = QCustomer.customer; + JPAQuery query = queryFactory.selectFrom(customer); + BooleanBuilder builder = new BooleanBuilder(); + for (String name : names) { + builder.or(customer.name.eq(name)); + } + query.where(builder); // customer.name eq name1 OR customer.name eq name2 OR ... + return query.fetch(); +} +``` + +`BooleanBuilder` is mutable and represents initially `null`. After each `and` +or `or` call it holds the result of the operation. + +## Dynamic Expressions + +The `com.querydsl.core.types.dsl.Expressions` class is a static factory class +for dynamic expression construction. The factory methods are named by the +returned type and are mostly self-documenting. + +In general, the `Expressions` class should only be used when the fluent DSL +forms are not available, such as dynamic paths, custom syntax, or custom +operations. + +The following expression: + +```java +QPerson person = QPerson.person; +person.firstName.startsWith("P"); +``` + +could be constructed like this if Q-types are not available: + +```java +Path person = Expressions.path(Person.class, "person"); +Path personFirstName = Expressions.path(String.class, person, "firstName"); +Constant constant = Expressions.constant("P"); +Expressions.predicate(Ops.STARTS_WITH, personFirstName, constant); +``` + +`Path` instances represent variables and properties, `Constant` instances are +constants, `Operation` instances are operations, and `TemplateExpression` +instances can be used to express expressions as string templates. + +## Dynamic Paths + +In addition to the `Expressions`-based expression creation, Querydsl provides +a more fluent API for dynamic path creation. + +For dynamic path generation, the `com.querydsl.core.types.dsl.PathBuilder` +class can be used. It extends `EntityPathBase` and can be used as an +alternative to class generation and alias usage for path generation. + +Compared to the `Expressions` API, `PathBuilder` does not provide direct +support for unknown operations or custom syntax, but the syntax is closer to +the normal DSL. + +String property: + +```java +PathBuilder entityPath = new PathBuilder(User.class, "entity"); +// fully generic access +entityPath.get("userName"); +// .. or with supplied type +entityPath.get("userName", String.class); +// .. and correct signature +entityPath.getString("userName").lower(); +``` + +List property with component type: + +```java +entityPath.getList("list", String.class).get(0); +``` + +Using a component expression type: + +```java +entityPath.getList("list", String.class, StringPath.class).get(0).lower(); +``` + +Map property with key and value type: + +```java +entityPath.getMap("map", String.class, String.class).get("key"); +``` + +Using a component expression type: + +```java +entityPath.getMap("map", String.class, String.class, StringPath.class).get("key").lower(); +``` + +For `PathBuilder` validation, a `PathBuilderValidator` can be injected in the +constructor and will be used transitively for new `PathBuilder` instances: + +```java +PathBuilder customer = new PathBuilder(Customer.class, "customer", validator); +``` + +`PathBuilderValidator.FIELDS` verifies field existence, +`PathBuilderValidator.PROPERTIES` validates Bean properties, and +`JPAPathBuilderValidator` validates using a JPA metamodel. + +## Case Expressions + +To construct case-when-then-else expressions, use the `CaseBuilder` class: + +```java +QCustomer customer = QCustomer.customer; +Expression cases = new CaseBuilder() + .when(customer.annualSpending.gt(10000)).then("Premier") + .when(customer.annualSpending.gt(5000)).then("Gold") + .when(customer.annualSpending.gt(2000)).then("Silver") + .otherwise("Bronze"); +// The cases expression can now be used in a projection or condition +``` + +For case expressions with equals-operations, use the simpler form: + +```java +QCustomer customer = QCustomer.customer; +Expression cases = customer.annualSpending + .when(10000).then("Premier") + .when(5000).then("Gold") + .when(2000).then("Silver") + .otherwise("Bronze"); +// The cases expression can now be used in a projection or condition +``` + +## Casting Expressions + +To avoid a generic signature in expression types, the type hierarchies are +flattened. The result is that all generated query types are direct subclasses +of `com.querydsl.core.types.dsl.EntityPathBase` or +`com.querydsl.core.types.dsl.BeanPath` and cannot be directly cast to their +logical supertypes. + +Instead of a direct Java cast, the supertype reference is accessible via the +`_super` field. A `_super` field is available in all generated query types with +a single supertype: + +```java +// from Account +QAccount extends EntityPathBase { + // ... +} + +// from BankAccount extends Account +QBankAccount extends EntityPathBase { + + public final QAccount _super = new QAccount(this); + + // ... +} +``` + +To cast from a supertype to a subtype, use the `as` method of the +`EntityPathBase` class: + +```java +QAccount account = new QAccount("account"); +QBankAccount bankAccount = account.as(QBankAccount.class); +``` + +## Select Literals + +Literals can be selected by referring to them via constant expressions: + +```java +query.select(Expressions.constant(1), + Expressions.constant("abc")); +``` + +Constant expressions are often used in subqueries. diff --git a/docs/guides/index.md b/docs/guides/index.md new file mode 100644 index 0000000000..9e892de9a0 --- /dev/null +++ b/docs/guides/index.md @@ -0,0 +1,11 @@ +--- +layout: default +title: Guides +nav_order: 4 +has_children: true +--- + +# Guides + +In-depth guides covering cross-cutting Querydsl features that apply to all +backend modules. diff --git a/docs/guides/result-handling.md b/docs/guides/result-handling.md new file mode 100644 index 0000000000..cef9e87b35 --- /dev/null +++ b/docs/guides/result-handling.md @@ -0,0 +1,163 @@ +--- +layout: default +title: Result Handling +parent: Guides +nav_order: 2 +--- + +# Result Handling + +Querydsl provides two ways to customize results: `FactoryExpression` for +row-based transformation and `ResultTransformer` for aggregation. + +The `com.querydsl.core.types.FactoryExpression` interface is used for bean +creation, constructor invocation, and for the creation of more complex objects. +The `FactoryExpression` implementations of Querydsl can be accessed via the +`com.querydsl.core.types.Projections` class. + +For the `com.querydsl.core.ResultTransformer` interface, `GroupBy` is the main +implementation. + +## Returning Multiple Columns + +The default type for multi-column results is `com.querydsl.core.Tuple`. Tuple +provides a type-safe Map-like interface to access column data from a Tuple row +object. + +```java +List result = query.select(employee.firstName, employee.lastName) + .from(employee).fetch(); +for (Tuple row : result) { + System.out.println("firstName " + row.get(employee.firstName)); + System.out.println("lastName " + row.get(employee.lastName)); +} +``` + +This example could also have been written via the `QTuple` expression class: + +```java +List result = query.select(new QTuple(employee.firstName, employee.lastName)) + .from(employee).fetch(); +for (Tuple row : result) { + System.out.println("firstName " + row.get(employee.firstName)); + System.out.println("lastName " + row.get(employee.lastName)); +} +``` + +## Bean Population + +In cases where beans need to be populated based on the results of the query, +bean projections can be used: + +```java +List dtos = query.select( + Projections.bean(UserDTO.class, user.firstName, user.lastName)).fetch(); +``` + +When fields should be used directly instead of setters: + +```java +List dtos = query.select( + Projections.fields(UserDTO.class, user.firstName, user.lastName)).fetch(); +``` + +## Constructor Usage + +Constructor-based row transformation: + +```java +List dtos = query.select( + Projections.constructor(UserDTO.class, user.firstName, user.lastName)).fetch(); +``` + +As an alternative to the generic constructor expression usage, constructors +can also be annotated with the `@QueryProjection` annotation: + +```java +class CustomerDTO { + + @QueryProjection + public CustomerDTO(long id, String name) { + ... + } + +} +``` + +Then use it in the query: + +```java +QCustomer customer = QCustomer.customer; +JPQLQuery query = new HibernateQuery(session); +List dtos = query.select(new QCustomerDTO(customer.id, customer.name)) + .from(customer).fetch(); +``` + +While the example is Hibernate-specific, this feature is available in all +modules. + +If the type with the `@QueryProjection` annotation is not an annotated entity +type, you can use the constructor projection like in the example. If the +annotated type is an entity type, the constructor projection needs to be +created via a call to the static `create` method of the query type: + +```java +@Entity +class Customer { + + @QueryProjection + public Customer(long id, String name) { + ... + } + +} +``` + +```java +QCustomer customer = QCustomer.customer; +JPQLQuery query = new HibernateQuery(session); +List dtos = query.select(QCustomer.create(customer.id, customer.name)) + .from(customer).fetch(); +``` + +Alternatively, if code generation is not an option: + +```java +List dtos = query + .select(Projections.constructor(Customer.class, customer.id, customer.name)) + .from(customer).fetch(); +``` + +## Result Aggregation + +The `com.querydsl.core.group.GroupBy` class provides aggregation functionality +which can be used to aggregate query results in memory. + +Aggregating parent-child relations: + +```java +import static com.querydsl.core.group.GroupBy.*; + +Map> results = query.from(post, comment) + .where(comment.post.id.eq(post.id)) + .transform(groupBy(post.id).as(list(comment))); +``` + +This returns a map of post ids to related comments. + +Multiple result columns: + +```java +Map results = query.from(post, comment) + .where(comment.post.id.eq(post.id)) + .transform(groupBy(post.id).as(post.name, set(comment.id))); +``` + +This returns a map of post ids to `Group` instances with access to post name +and comment ids. + +`Group` is the `GroupBy` equivalent to the `Tuple` interface. + +More examples can be found in the +[GroupByTest](https://github.com/OpenFeign/querydsl/blob/master/querydsl-libraries/querydsl-collections/src/test/java/com/querydsl/collections/GroupByTest.java) +class. diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000000..4962ab8f9e --- /dev/null +++ b/docs/index.md @@ -0,0 +1,71 @@ +--- +layout: default +title: Home +nav_order: 1 +--- + +# Querydsl Reference Documentation +{: .fs-9 } + +Type-safe SQL-like queries for Java. +{: .fs-6 .fw-300 } + +[Get Started with JPA]({{ site.baseurl }}/tutorials/jpa){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } +[View on GitHub](https://github.com/OpenFeign/querydsl){: .btn .fs-5 .mb-4 .mb-md-0 } + +--- + +Querydsl is a framework that enables the construction of statically typed +SQL-like queries for multiple backends in Java. Instead of writing queries as +inline strings or externalizing them into XML files, you construct them via a +fluent API. + +## Benefits + +- **Code completion in your IDE** — discover available columns and operations as + you type. +- **Syntactically valid queries** — the compiler catches most query mistakes + before runtime. +- **Safe domain references** — properties are referenced through generated + types, not strings. +- **Refactoring friendly** — rename a field and every query that uses it updates + automatically. + +## Supported Backends + +| Module | Artifact | +|:-------|:---------| +| [JPA (Hibernate / EclipseLink)]({{ site.baseurl }}/tutorials/jpa) | `{{ site.group_id }}:querydsl-jpa` | +| [SQL (JDBC)]({{ site.baseurl }}/tutorials/sql) | `{{ site.group_id }}:querydsl-sql` | +| [R2DBC (Reactive SQL)]({{ site.baseurl }}/tutorials/r2dbc) | `{{ site.group_id }}:querydsl-r2dbc` | +| [MongoDB]({{ site.baseurl }}/tutorials/mongodb) | `{{ site.group_id }}:querydsl-mongodb` | +| [Collections]({{ site.baseurl }}/tutorials/collections) | `{{ site.group_id }}:querydsl-collections` | +| [Spatial]({{ site.baseurl }}/tutorials/spatial) | `{{ site.group_id }}:querydsl-sql-spatial` | +| [Kotlin Extensions]({{ site.baseurl }}/tutorials/kotlin) | `{{ site.group_id }}:querydsl-kotlin` | +| [Scala Extensions]({{ site.baseurl }}/tutorials/scala) | `{{ site.group_id }}:querydsl-scala` | + +## Quick Example + +```java +QCustomer customer = QCustomer.customer; +List bobs = queryFactory.selectFrom(customer) + .where(customer.firstName.eq("Bob")) + .orderBy(customer.lastName.asc()) + .fetch(); +``` + +## Current Version + +The latest release is **{{ site.querydsl_version }}**. Add it to your Maven +project: + +```xml + + {{ site.group_id }} + querydsl-jpa + {{ site.querydsl_version }} + +``` + +See the [Migration Guide]({{ site.baseurl }}/migration) if you are upgrading +from the original `com.querydsl` artifacts. diff --git a/docs/introduction.md b/docs/introduction.md new file mode 100644 index 0000000000..ece1714cf1 --- /dev/null +++ b/docs/introduction.md @@ -0,0 +1,42 @@ +--- +layout: default +title: Introduction +nav_order: 2 +--- + +# Introduction + +## Background + +Querydsl was born out of the need to maintain HQL queries in a type-safe way. +Building HQL queries incrementally requires string concatenation, which +produces hard-to-read code. Referencing domain types and properties through +plain strings is fragile and error-prone. + +With a changing domain model, type safety brings huge benefits. Domain changes +are reflected directly in queries, and IDE auto-complete makes query +construction faster and safer. + +HQL for Hibernate was the first target language for Querydsl. Today the +framework supports **JPA**, **SQL (JDBC)**, **R2DBC**, **MongoDB**, +**Collections**, **Spatial**, **Kotlin**, and **Scala** as backends. + +If you are new to database access in Java, +[this guide](https://www.marcobehler.com/guides/a-guide-to-accessing-databases-in-java) +provides a good overview of the various parts and options and shows where +Querydsl fits in. + +## Principles + +**Type safety** is the core principle of Querydsl. Queries are constructed +based on generated query types that reflect the properties of your domain +types. Function and method invocations are constructed in a fully type-safe +manner. + +**Consistency** is another important principle. The query paths and operations +are the same across all implementations, and the query interfaces share a +common base interface. + +To get an impression of the expressivity of the Querydsl query and expression +types, explore the Javadocs for `com.querydsl.core.Query`, +`com.querydsl.core.Fetchable`, and `com.querydsl.core.types.Expression`. diff --git a/docs/migration.md b/docs/migration.md new file mode 100644 index 0000000000..4226447aaa --- /dev/null +++ b/docs/migration.md @@ -0,0 +1,237 @@ +--- +layout: default +title: Migration Guide +nav_order: 6 +--- + +# Migration Guide + +The original Querydsl project (`com.querydsl`, hosted at querydsl.com) has +been inactive since 2020. The last release, 5.0.0, was published in July 2021. +The website querydsl.com and its documentation may go offline at any time. + +This fork, maintained under the [OpenFeign](https://github.com/OpenFeign) +organization, provides regular releases, community patches, Jakarta EE +support, and new modules like R2DBC and Kotlin. This guide covers everything +you need to migrate. + +## Why Migrate? + +- **Active maintenance** — regular releases, dependency updates, security + patches +- **Jakarta EE support** — works with Hibernate 6+, Spring Boot 3+, and + Jakarta-namespace APIs +- **Java 17+** — takes advantage of modern JDK features +- **New modules** — R2DBC for reactive database access, Kotlin extensions for + idiomatic syntax +- **Community-driven** — PRs are reviewed and merged, issues get attention + +## What Stays the Same + +- **Java package names** — all classes remain in `com.querydsl.*` packages. No + source code changes are needed for import statements. +- **Artifact IDs** — `querydsl-jpa`, `querydsl-sql`, `querydsl-mongodb`, etc. + are unchanged. +- **API surface** — the Querydsl fluent API is the same. Your existing query + code will compile and run without changes (after the groupId and namespace + migration below). + +## What Changes + +### 1. Maven GroupId + +Replace all occurrences of `com.querydsl` with `{{ site.group_id }}`: + +**Before:** + +```xml + + com.querydsl + querydsl-jpa + 5.0.0 + +``` + +**After:** + +```xml + + {{ site.group_id }} + querydsl-jpa + {{ site.querydsl_version }} + +``` + +A quick way to do this across your project: + +```bash +find . -name "pom.xml" -exec sed -i 's|com.querydsl|{{ site.group_id }}|g' {} + +``` + +### 2. Jakarta EE (javax → jakarta) + +Starting with version 6.0, this fork requires **Jakarta EE** (the +`jakarta.*` namespace) instead of Java EE (`javax.*`). + +| Before | After | +|:-------|:------| +| `javax.persistence.Entity` | `jakarta.persistence.Entity` | +| `javax.persistence.EntityManager` | `jakarta.persistence.EntityManager` | +| `javax.inject.Inject` | `jakarta.inject.Inject` | +| `javax.annotation.Generated` | `jakarta.annotation.Generated` | + +You also need Jakarta-compatible versions of your JPA provider: + +| Provider | Minimum Version | +|:---------|:----------------| +| Hibernate | 6.0+ | +| EclipseLink | 4.0+ | +| Spring Boot | 3.0+ | + +### 3. Java Version + +This fork requires **Java 17** or later. If you are on Java 8 or 11, you need +to upgrade your JDK before migrating. + +### 4. Annotation Processor Configuration + +The old `com.mysema.maven:apt-maven-plugin` is no longer recommended. Use +`maven-compiler-plugin` with annotation processor dependencies instead: + +**Before (apt-maven-plugin):** + +```xml + + com.mysema.maven + apt-maven-plugin + 1.1.3 + + + + process + + + target/generated-sources/java + com.querydsl.apt.jpa.JPAAnnotationProcessor + + + + +``` + +**After (maven-compiler-plugin):** + +```xml + + maven-compiler-plugin + + target/generated-sources/java + + + + {{ site.group_id }} + querydsl-apt + {{ site.querydsl_version }} + jpa + + + jakarta.persistence + jakarta.persistence-api + 3.1.0 + + + +``` + +Available classifiers for `querydsl-apt`: + +| Classifier | Annotation Processor | +|:-----------|:--------------------| +| `jpa` | `JPAAnnotationProcessor` | +| `hibernate` | `HibernateAnnotationProcessor` | +| `general` | `QuerydslAnnotationProcessor` | + +### 5. Removed Modules + +The following modules have been removed from this fork: + +| Module | Reason | Alternative | +|:-------|:-------|:------------| +| `querydsl-jdo` | JDO usage has declined significantly | Use JPA instead | +| `querydsl-lucene3` | Lucene 3 is EOL | Use Lucene/Elasticsearch client directly | +| `querydsl-lucene4` | Lucene 4 is EOL | Use Lucene/Elasticsearch client directly | +| `querydsl-lucene5` | Lucene integration is rarely used | Use Lucene/Elasticsearch client directly | +| `querydsl-hibernate-search` | Hibernate Search has its own query DSL | Use Hibernate Search API directly | + +If you depend on any of these modules, you have two options: +1. Keep using the original `com.querydsl:5.0.0` artifacts for those specific + modules alongside the new fork for everything else (the Java packages are + the same, so be careful with classpath conflicts). +2. Migrate to the native APIs of those backends. + +### 6. New Modules + +| Module | Description | +|:-------|:------------| +| [`querydsl-r2dbc`]({{ site.baseurl }}/tutorials/r2dbc) | Reactive, non-blocking database access via R2DBC and Project Reactor | +| [`querydsl-kotlin`]({{ site.baseurl }}/tutorials/kotlin) | Kotlin extension functions — use `+`, `-`, `*`, `/`, `%` operators on expressions | + +## Step-by-Step Migration + +1. **Upgrade your JDK** to 17 or later. +2. **Migrate to Jakarta EE** if not already done — replace `javax.persistence` + with `jakarta.persistence`, update your JPA provider. +3. **Update your POM** — change the groupId from `com.querydsl` to + `{{ site.group_id }}` for all Querydsl dependencies. +4. **Update the version** — set the version to `{{ site.querydsl_version }}`. +5. **Replace apt-maven-plugin** — switch to `maven-compiler-plugin` with + `querydsl-apt` as a compiler dependency. +6. **Remove references to dropped modules** — if you used `querydsl-jdo`, + `querydsl-lucene*`, or `querydsl-hibernate-search`, find alternatives. +7. **Clean and rebuild** — run `mvn clean install` to regenerate all Q-types. +8. **Run your tests** — verify that all queries work as expected. + +## Gradle Users + +For Gradle, the same groupId change applies: + +**Before:** + +```groovy +implementation 'com.querydsl:querydsl-jpa:5.0.0' +annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jpa' +``` + +**After:** + +```groovy +implementation '{{ site.group_id }}:querydsl-jpa:{{ site.querydsl_version }}' +annotationProcessor '{{ site.group_id }}:querydsl-apt:{{ site.querydsl_version }}:jpa' +``` + +## Spring Boot Integration + +If you use Spring Boot 3+, the migration is straightforward since Spring Boot +3 already requires Jakarta EE and Java 17: + +```xml + + {{ site.querydsl_version }} + + + + + {{ site.group_id }} + querydsl-jpa + ${querydsl.version} + + +``` + +For Spring Boot 2.x users: you need to migrate to Spring Boot 3+ first (which +also requires Jakarta EE and Java 17), and then migrate Querydsl. + +## Getting Help + +If you encounter issues during migration, open a discussion on the +[GitHub repository](https://github.com/OpenFeign/querydsl/discussions). diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md new file mode 100644 index 0000000000..e4e6235968 --- /dev/null +++ b/docs/troubleshooting.md @@ -0,0 +1,51 @@ +--- +layout: default +title: Troubleshooting +nav_order: 5 +--- + +# Troubleshooting + +## Insufficient Type Arguments + +Querydsl needs properly encoded `List`, `Set`, `Collection`, and `Map` +properties in all code generation scenarios. + +When using improperly encoded fields or getters you might see the following +stack trace: + +``` +java.lang.RuntimeException: Caught exception for field com.querydsl.jdo.testdomain.Store#products + at com.querydsl.apt.Processor$2.visitType(Processor.java:117) + at com.querydsl.apt.Processor$2.visitType(Processor.java:80) + ... +Caused by: java.lang.IllegalArgumentException: Insufficient type arguments for List + at com.querydsl.apt.APTTypeModel.visitDeclared(APTTypeModel.java:112) + ... +``` + +Examples of problematic field declarations and their corrections: + +```java +private Collection names; // WRONG +private Collection names; // RIGHT + +private Map employeesByName; // WRONG +private Map employeesByName; // RIGHT +``` + +## Multithreaded Initialization of Querydsl Q-types + +When Querydsl Q-types are initialized from multiple threads, deadlocks can +occur if the Q-types have circular dependencies. + +The solution is to initialize the classes in a single thread before they are +used in different threads. + +The `com.querydsl.codegen.ClassPathUtils` class can be used for that: + +```java +ClassPathUtils.scanPackage(Thread.currentThread().getContextClassLoader(), packageToLoad); +``` + +Replace `packageToLoad` with the package of the classes you want to initialize. diff --git a/docs/tutorials/collections.md b/docs/tutorials/collections.md new file mode 100644 index 0000000000..1604a1abb0 --- /dev/null +++ b/docs/tutorials/collections.md @@ -0,0 +1,154 @@ +--- +layout: default +title: Querying Collections +parent: Tutorials +nav_order: 4 +--- + +# Querying Collections + +The `querydsl-collections` module can be used with generated query types or +without. The first section describes usage without generated query types. + +## Usage Without Generated Query Types + +To use `querydsl-collections` without generated query types, use the Querydsl +alias feature. + +Add the following static imports: + +```java +// needed for access of the Querydsl Collections API +import static com.querydsl.collections.CollQueryFactory.*; +// needed if you use the $-invocations +import static com.querydsl.core.alias.Alias.*; +``` + +Create an alias instance for the `Cat` class. Alias instances can only be +created for non-final classes with an empty constructor. + +The alias instance and its getter invocations are transformed into paths by +wrapping them in dollar-method invocations. The call `c.getKittens()` is +internally transformed into the property path `c.kittens` inside the dollar +method. + +```java +Cat c = alias(Cat.class, "cat"); +for (String name : select($(c.getName())).from($(c),cats) + .where($(c.getKittens()).size().gt(0)) + .fetch()) { + System.out.println(name); +} +``` + +The following example is a variation where the access to the list size happens +inside the dollar-method invocation: + +```java +Cat c = alias(Cat.class, "cat"); +for (String name : select($(c.getName())).from($(c),cats) + .where($(c.getKittens().size()).gt(0)) + .fetch()) { + System.out.println(name); +} +``` + +All non-primitive and non-final typed properties of aliases are aliases +themselves. You may cascade method calls until you hit a primitive or final +type in the dollar-method scope, e.g.: + +```java +$(c.getMate().getName()) +``` + +is transformed into `c.mate.name` internally, but: + +```java +$(c.getMate().getName().toLowerCase()) +``` + +is not transformed properly, since the `toLowerCase()` invocation is not +tracked. + +You may only invoke getters, `size()`, `contains(Object)`, and `get(int)` on +alias types. All other invocations throw exceptions. + +## Usage With Generated Query Types + +The same query expressed with generated expression types: + +```java +QCat cat = new QCat("cat"); +for (String name : select(cat.name).from(cat,cats) + .where(cat.kittens.size().gt(0)) + .fetch()) { + System.out.println(name); +} +``` + +When you use generated query types, you instantiate expressions instead of +alias instances and use the property paths directly without any dollar-method +wrapping. + +## Maven Integration + +Add the following dependencies to your Maven project: + +```xml + + {{ site.group_id }} + querydsl-collections + {{ site.querydsl_version }} + +``` + +If you are not using JPA you can generate expression types for your domain +types by annotating them with `com.querydsl.core.annotations.QueryEntity` and +configuring the `maven-compiler-plugin`: + +```xml + + maven-compiler-plugin + + target/generated-sources/java + + + + {{ site.group_id }} + querydsl-apt + {{ site.querydsl_version }} + general + + + +``` + +## Hamcrest Matchers + +Querydsl Collections provides Hamcrest matchers: + +```java +import static org.hamcrest.core.IsEqual.equalTo; +import static com.querydsl.collections.PathMatcher.hasValue; +import static org.junit.Assert.assertThat; + +Car car = new Car(); +car.setHorsePower(123); + +assertThat(car, hasValue($.horsePower)); +assertThat(car, hasValue($.horsePower, equalTo(123))); +``` + +## Usage With the Eclipse Compiler for Java + +If `querydsl-collections` is used with a JRE where the system compiler is not +available, `CollQuery` instances can be configured to use the Eclipse Compiler +for Java (ECJ) instead: + +```java +DefaultEvaluatorFactory evaluatorFactory = new DefaultEvaluatorFactory( + CollQueryTemplates.DEFAULT, + new ECJEvaluatorFactory(getClass().getClassLoader())); +QueryEngine queryEngine = new DefaultQueryEngine(evaluatorFactory); +CollQuery query = new CollQuery(queryEngine); +``` diff --git a/docs/tutorials/index.md b/docs/tutorials/index.md new file mode 100644 index 0000000000..f675234f3e --- /dev/null +++ b/docs/tutorials/index.md @@ -0,0 +1,13 @@ +--- +layout: default +title: Tutorials +nav_order: 3 +has_children: true +--- + +# Tutorials + +Step-by-step guides for using Querydsl with each supported backend. + +Each tutorial covers Maven setup, code generation, and query construction +for a specific integration module. diff --git a/docs/tutorials/jpa.md b/docs/tutorials/jpa.md new file mode 100644 index 0000000000..fb2631f588 --- /dev/null +++ b/docs/tutorials/jpa.md @@ -0,0 +1,472 @@ +--- +layout: default +title: Querying JPA +parent: Tutorials +nav_order: 1 +--- + +# Querying JPA + +Querydsl defines a general statically typed syntax for querying on top of +persisted domain model data. This guide describes how to use Querydsl in +combination with JPA. + +Querydsl for JPA is an alternative to both JPQL and Criteria queries. It +combines the dynamic nature of Criteria queries with the expressiveness of +JPQL — all in a fully type-safe manner. + +## Maven Integration + +Add the following dependencies to your Maven project: + +```xml + + {{ site.group_id }} + querydsl-jpa + {{ site.querydsl_version }} + +``` + +Configure the `maven-compiler-plugin` to run the Querydsl annotation processor +during compilation: + +```xml + + maven-compiler-plugin + + target/generated-sources/java + + + + {{ site.group_id }} + querydsl-apt + {{ site.querydsl_version }} + jpa + + + jakarta.persistence + jakarta.persistence-api + 3.1.0 + + + +``` + +The `JPAAnnotationProcessor` finds domain types annotated with the +`jakarta.persistence.Entity` annotation and generates query types for them. + +If you use Hibernate annotations in your domain types, use the processor +`com.querydsl.apt.hibernate.HibernateAnnotationProcessor` instead. + +Run `mvn clean install` and your query types will be generated into +`target/generated-sources/java`. + +## Generating the Model from hbm.xml Files + +If you use Hibernate with an XML-based configuration, you can use the XML +metadata to create your Querydsl model. + +`com.querydsl.jpa.codegen.HibernateDomainExporter` provides this +functionality: + +```java +HibernateDomainExporter exporter = new HibernateDomainExporter( + "Q", // name prefix + new File("target/gen3"), // target folder + configuration); // instance of org.hibernate.cfg.Configuration + +exporter.export(); +``` + +The `HibernateDomainExporter` must be executed within a classpath where the +domain types are visible, since property types are resolved via reflection. + +All JPA annotations are ignored, but Querydsl annotations such as `@QueryInit` +and `@QueryType` are taken into account. + +## Using Query Types + +To create queries with Querydsl you need to instantiate variables and query +implementations. + +Assume that your project has the following domain type: + +```java +@Entity +public class Customer { + private String firstName; + private String lastName; + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public void setFirstName(String fn) { + firstName = fn; + } + + public void setLastName(String ln) { + lastName = ln; + } +} +``` + +Querydsl generates a query type with the simple name `QCustomer` into the same +package as `Customer`. `QCustomer` can be used as a statically typed variable +in Querydsl queries as a representative for the `Customer` type. + +`QCustomer` has a default instance variable accessible as a static field: + +```java +QCustomer customer = QCustomer.customer; +``` + +Alternatively, define your own variable: + +```java +QCustomer customer = new QCustomer("myCustomer"); +``` + +## Querying + +The Querydsl JPA module supports both the JPA and the Hibernate API. + +To use the JPA API, create `JPAQuery` instances like this: + +```java +// where entityManager is a JPA EntityManager +JPAQuery query = new JPAQuery(entityManager); +``` + +If you use the Hibernate API instead, instantiate a `HibernateQuery`: + +```java +// where session is a Hibernate session +HibernateQuery query = new HibernateQuery(session); +``` + +Both `JPAQuery` and `HibernateQuery` implement the `JPQLQuery` interface. + +For the examples in this chapter, queries are created via a `JPAQueryFactory` +instance. `JPAQueryFactory` should be the preferred option for obtaining +`JPAQuery` instances. For the Hibernate API, `HibernateQueryFactory` can be +used. + +To retrieve the customer with the first name Bob: + +```java +QCustomer customer = QCustomer.customer; +Customer bob = queryFactory.selectFrom(customer) + .where(customer.firstName.eq("Bob")) + .fetchOne(); +``` + +The `selectFrom` call defines the query source and projection, the `where` +part defines the filter, and `fetchOne` tells Querydsl to return a single +element. + +To create a query with multiple sources: + +```java +QCustomer customer = QCustomer.customer; +QCompany company = QCompany.company; +query.from(customer, company); +``` + +To use multiple filters: + +```java +queryFactory.selectFrom(customer) + .where(customer.firstName.eq("Bob"), customer.lastName.eq("Wilson")); +``` + +Or equivalently: + +```java +queryFactory.selectFrom(customer) + .where(customer.firstName.eq("Bob").and(customer.lastName.eq("Wilson"))); +``` + +In native JPQL form the query would be: + +``` +select customer from Customer as customer +where customer.firstName = "Bob" and customer.lastName = "Wilson" +``` + +To combine the filters via "or": + +```java +queryFactory.selectFrom(customer) + .where(customer.firstName.eq("Bob").or(customer.lastName.eq("Wilson"))); +``` + +## Using Joins + +Querydsl supports the following join variants in JPQL: inner join, join, left +join, and right join. Join usage is type-safe and follows this pattern: + +```java +QCat cat = QCat.cat; +QCat mate = new QCat("mate"); +QCat kitten = new QCat("kitten"); +queryFactory.selectFrom(cat) + .innerJoin(cat.mate, mate) + .leftJoin(cat.kittens, kitten) + .fetch(); +``` + +The native JPQL version: + +``` +select cat from Cat as cat +inner join cat.mate as mate +left outer join cat.kittens as kitten +``` + +Another example: + +```java +queryFactory.selectFrom(cat) + .leftJoin(cat.kittens, kitten) + .on(kitten.bodyWeight.gt(10.0)) + .fetch(); +``` + +## General Usage + +Use the cascading methods of the `JPQLQuery` interface: + +- **select:** Set the projection of the query. (Not necessary if created via + query factory) +- **from:** Add query sources. +- **innerJoin, join, leftJoin, rightJoin, on:** Add join elements. For join + methods, the first argument is the join source and the second the target + (alias). +- **where:** Add query filters, either in varargs form separated via commas or + cascaded via the `and` operator. +- **groupBy:** Add group by arguments in varargs form. +- **having:** Add having filters of the "group by" grouping as a varargs array + of Predicate expressions. +- **orderBy:** Add ordering of the result as a varargs array of order + expressions. Use `asc()` and `desc()` on numeric, string, and other + comparable expressions to access `OrderSpecifier` instances. +- **limit, offset, restrict:** Set the paging of the result. `limit` for max + results, `offset` for skipping rows, and `restrict` for defining both in one + call. + +## Ordering + +```java +QCustomer customer = QCustomer.customer; +queryFactory.selectFrom(customer) + .orderBy(customer.lastName.asc(), customer.firstName.desc()) + .fetch(); +``` + +Equivalent native JPQL: + +``` +select customer from Customer as customer +order by customer.lastName asc, customer.firstName desc +``` + +## Grouping + +```java +queryFactory.select(customer.lastName).from(customer) + .groupBy(customer.lastName) + .fetch(); +``` + +Equivalent native JPQL: + +``` +select customer.lastName +from Customer as customer +group by customer.lastName +``` + +## Delete Clauses + +Delete clauses follow a simple delete-where-execute form: + +```java +QCustomer customer = QCustomer.customer; +// delete all customers +queryFactory.delete(customer).execute(); +// delete all customers with a level less than 3 +queryFactory.delete(customer).where(customer.level.lt(3)).execute(); +``` + +The `where` call is optional and `execute` performs the deletion and returns +the number of deleted entities. + +DML clauses in JPA do not take JPA-level cascade rules into account and do not +provide fine-grained second-level cache interaction. + +## Update Clauses + +Update clauses follow a simple update-set/where-execute form: + +```java +QCustomer customer = QCustomer.customer; +// rename customers named Bob to Bobby +queryFactory.update(customer).where(customer.name.eq("Bob")) + .set(customer.name, "Bobby") + .execute(); +``` + +The `set` invocations define the property updates in SQL-Update style and +`execute` performs the update and returns the number of updated entities. + +DML clauses in JPA do not take JPA-level cascade rules into account and do not +provide fine-grained second-level cache interaction. + +## Subqueries + +To create a subquery, use the static factory methods of `JPAExpressions` and +define the query parameters via `from`, `where`, etc. + +```java +QDepartment department = QDepartment.department; +QDepartment d = new QDepartment("d"); +queryFactory.selectFrom(department) + .where(department.size.eq( + JPAExpressions.select(d.size.max()).from(d))) + .fetch(); +``` + +Another example: + +```java +QEmployee employee = QEmployee.employee; +QEmployee e = new QEmployee("e"); +queryFactory.selectFrom(employee) + .where(employee.weeklyhours.gt( + JPAExpressions.select(e.weeklyhours.avg()) + .from(employee.department.employees, e) + .where(e.manager.eq(employee.manager)))) + .fetch(); +``` + +## Exposing the Original Query + +If you need to tune the original JPA `Query` before execution, you can expose +it: + +```java +Query jpaQuery = queryFactory.selectFrom(employee).createQuery(); +// ... +List results = jpaQuery.getResultList(); +``` + +## Using Native SQL in JPA Queries + +Querydsl supports Native SQL in JPA via the `JPASQLQuery` class. + +To use it, you must generate Querydsl query types for your SQL schema. This +can be done with the following Maven configuration: + +```xml + + {{ site.group_id }} + querydsl-maven-plugin + {{ site.querydsl_version }} + + + + export + + + + + org.apache.derby.jdbc.EmbeddedDriver + jdbc:derby:target/demoDB;create=true + com.mycompany.mydomain + ${project.basedir}/target/generated-sources/java + + + + org.apache.derby + derby + ${derby.version} + + + +``` + +When the query types have been generated, you can use them in your queries. + +Single column query: + +```java +// serialization templates +SQLTemplates templates = new DerbyTemplates(); +// query types (S* for SQL, Q* for domain types) +SAnimal cat = new SAnimal("cat"); +SAnimal mate = new SAnimal("mate"); +QCat catEntity = QCat.cat; + +JPASQLQuery query = new JPASQLQuery(entityManager, templates); +List names = query.select(cat.name).from(cat).fetch(); +``` + +If you mix entity (e.g. `QCat`) and table (e.g. `SAnimal`) references in your +query, make sure they use the same variable names. `SAnimal.animal` has the +variable name "animal", so a new instance (`new SAnimal("cat")`) was used +instead. + +An alternative pattern: + +```java +QCat catEntity = QCat.cat; +SAnimal cat = new SAnimal(catEntity.getMetadata().getName()); +``` + +Query multiple columns: + +```java +query = new JPASQLQuery(entityManager, templates); +List rows = query.select(cat.id, cat.name).from(cat).fetch(); +``` + +Query all columns: + +```java +List rows = query.select(cat.all()).from(cat).fetch(); +``` + +Query in SQL, but project as entity: + +```java +query = new JPASQLQuery(entityManager, templates); +List cats = query.select(catEntity).from(cat).orderBy(cat.name.asc()).fetch(); +``` + +Query with joins: + +```java +query = new JPASQLQuery(entityManager, templates); +cats = query.select(catEntity).from(cat) + .innerJoin(mate).on(cat.mateId.eq(mate.id)) + .where(cat.dtype.eq("Cat"), mate.dtype.eq("Cat")) + .fetch(); +``` + +Query and project into DTO: + +```java +query = new JPASQLQuery(entityManager, templates); +List catDTOs = query.select(Projections.constructor(CatDTO.class, cat.id, cat.name)) + .from(cat) + .orderBy(cat.name.asc()) + .fetch(); +``` + +If you use the Hibernate API instead of the JPA API, use `HibernateSQLQuery` +instead. diff --git a/docs/tutorials/kotlin.md b/docs/tutorials/kotlin.md new file mode 100644 index 0000000000..b419395253 --- /dev/null +++ b/docs/tutorials/kotlin.md @@ -0,0 +1,128 @@ +--- +layout: default +title: Querying in Kotlin +parent: Tutorials +nav_order: 8 +--- + +# Querying in Kotlin + +The `querydsl-kotlin` module provides Kotlin extension functions that make +Querydsl expressions feel natural in Kotlin code. Operator overloading allows +you to write queries using standard Kotlin operators. + +## Maven Integration + +Add the following dependency to your Maven project: + +```xml + + {{ site.group_id }} + querydsl-kotlin + {{ site.querydsl_version }} + +``` + +You also need the Querydsl module for your backend (e.g. `querydsl-jpa`, +`querydsl-sql`). Code generation works the same as with Java — use the +annotation processor for JPA or the Maven plugin for SQL. + +## Kotlin Operator Extensions + +The `querydsl-kotlin` module provides operator overloads for Querydsl +expressions, enabling idiomatic Kotlin syntax. + +### Boolean Operations + +```kotlin +import com.querydsl.kotlin.* + +val customer = QCustomer.customer + +// Standard Querydsl Kotlin alternative +customer.active.not() // !customer.active +customer.active + .and(customer.verified) // customer.active and customer.verified +customer.active + .or(customer.verified) // customer.active or customer.verified +``` + +### Comparison Operations + +```kotlin +// Standard Querydsl Kotlin alternative +customer.age.lt(5) // customer.age < 5 (not supported as operator) +customer.age.loe(5) // customer.age <= 5 (not supported as operator) +customer.age.gt(5) // customer.age > 5 (not supported as operator) +customer.age.goe(5) // customer.age >= 5 (not supported as operator) +customer.age.negate() // -customer.age +``` + +### Numeric Operations + +```kotlin +// Standard Querydsl Kotlin alternative +customer.age.add(3) // customer.age + 3 +customer.age.subtract(3) // customer.age - 3 +customer.age.multiply(3) // customer.age * 3 +customer.age.divide(3) // customer.age / 3 +customer.age.mod(5) // customer.age % 5 +``` + +These operators work with both expressions and literal values: + +```kotlin +// With another expression +customer.age + customer.bonusYears + +// With a literal +customer.age + 3 +``` + +### String Operations + +```kotlin +// Standard Querydsl Kotlin alternative +customer.firstName.append("X") // customer.firstName + "X" +customer.firstName.append(suffix) // customer.firstName + suffix +customer.firstName.charAt(0) // customer.firstName[0] +``` + +## Example Queries + +### JPA with Kotlin + +```kotlin +val customer = QCustomer.customer + +// Simple query +val bobs: List = queryFactory.selectFrom(customer) + .where(customer.firstName.eq("Bob")) + .fetch() + +// Using Kotlin operators for complex conditions +val results = queryFactory.selectFrom(customer) + .where( + customer.firstName.eq("Bob") + .and(customer.age + 5 > customer.minAge) + ) + .orderBy(customer.lastName.asc()) + .fetch() +``` + +### SQL with Kotlin + +```kotlin +val employee = QEmployee.employee + +val names = queryFactory.select(employee.firstName + " " + employee.lastName) + .from(employee) + .where(employee.salary * 12 > 100_000) + .fetch() +``` + +## Using with Other Backends + +The Kotlin extension functions work with any Querydsl backend — JPA, SQL, +R2DBC, MongoDB, or Collections. Import `com.querydsl.kotlin.*` and the +operators become available on all expression types. diff --git a/docs/tutorials/mongodb.md b/docs/tutorials/mongodb.md new file mode 100644 index 0000000000..f00fd4fca4 --- /dev/null +++ b/docs/tutorials/mongodb.md @@ -0,0 +1,130 @@ +--- +layout: default +title: Querying MongoDB +parent: Tutorials +nav_order: 3 +--- + +# Querying MongoDB + +This chapter describes the querying functionality of the MongoDB module. + +## Maven Integration + +Add the following dependencies to your Maven project: + +```xml + + {{ site.group_id }} + querydsl-mongodb + {{ site.querydsl_version }} + +``` + +Configure the `maven-compiler-plugin` to run the Querydsl annotation processor: + +```xml + + maven-compiler-plugin + + target/generated-sources/java + + + + {{ site.group_id }} + querydsl-apt + {{ site.querydsl_version }} + morphia + + + +``` + +The `MorphiaAnnotationProcessor` finds domain types annotated with +`com.google.code.morphia.annotations.Entity` and generates Querydsl query +types for them. + +Run `mvn clean install` and your query types will be generated into +`target/generated-sources/java`. + +## Querying + +Querying with Querydsl MongoDB with Morphia: + +```java +Morphia morphia; +Datastore datastore; +// ... +QUser user = new QUser("user"); +MorphiaQuery query = new MorphiaQuery(morphia, datastore, user); +List list = query + .where(user.firstName.eq("Bob")) + .fetch(); +``` + +## General Usage + +Use the cascading methods of the `MongodbQuery` class: + +- **where:** Add query filters, either in varargs form separated via commas or + cascaded via the `and` operator. Supported operations are operations + performed on PStrings except `matches`, `indexOf`, and `charAt`. +- **orderBy:** Add ordering of the result as a varargs array of order + expressions. Use `asc()` and `desc()` on numeric, string, and other + comparable expressions to access `OrderSpecifier` instances. +- **limit, offset, restrict:** Set the paging of the result. `limit` for max + results, `offset` for skipping rows, and `restrict` for defining both in one + call. + +## Ordering + +```java +query + .where(doc.title.like("*")) + .orderBy(doc.title.asc(), doc.year.desc()) + .fetch(); +``` + +The results are sorted ascending based on title and descending based on year. + +## Limit + +```java +query + .where(doc.title.like("*")) + .limit(10) + .fetch(); +``` + +## Offset + +```java +query + .where(doc.title.like("*")) + .offset(3) + .fetch(); +``` + +## Geospatial Queries + +Support for geospatial queries is available for `Double` typed arrays +(`Double[]`) via the `near` method: + +```java +query + .where(geoEntity.location.near(50.0, 50.0)) + .fetch(); +``` + +## Select Only Relevant Fields + +To select only relevant fields, use the overloaded projection methods +`fetch`, `iterate`, `fetchOne`, and `fetchFirst`: + +```java +query + .where(doc.title.like("*")) + .fetch(doc.title, doc.path); +``` + +This query loads only the `title` and `path` fields of the documents. diff --git a/docs/tutorials/r2dbc.md b/docs/tutorials/r2dbc.md new file mode 100644 index 0000000000..20c7637b9a --- /dev/null +++ b/docs/tutorials/r2dbc.md @@ -0,0 +1,232 @@ +--- +layout: default +title: Querying R2DBC +parent: Tutorials +nav_order: 5 +--- + +# Querying R2DBC + +The `querydsl-r2dbc` module provides reactive, non-blocking database access +built on [R2DBC](https://r2dbc.io/) and [Project Reactor](https://projectreactor.io/). +The API mirrors the SQL module but returns `Mono` and `Flux` types instead of +blocking results. + +## Maven Integration + +Add the following dependencies to your Maven project: + +```xml + + {{ site.group_id }} + querydsl-r2dbc + {{ site.querydsl_version }} + +``` + +You also need an R2DBC driver for your database, for example: + +```xml + + + org.postgresql + r2dbc-postgresql + +``` + +Code generation for the query types works exactly like the +[SQL module]({{ site.baseurl }}/tutorials/sql#code-generation-via-maven) — use the +`querydsl-maven-plugin` or `querydsl-sql-codegen` to export your schema. + +## Configuration + +Configuration is done via `com.querydsl.r2dbc.Configuration`, which takes a +Querydsl SQL dialect as an argument: + +```java +SQLTemplates templates = new PostgreSQLTemplates(); +Configuration configuration = new Configuration(templates); +``` + +The same `SQLTemplates` classes used by the SQL module are reused for R2DBC. +See the [SQL tutorial]({{ site.baseurl }}/tutorials/sql#configuration) for the +full list of available dialects. + +## Connection Provider + +R2DBC queries require an `R2DBCConnectionProvider` to obtain reactive +connections. The simplest way to create one is from a `ConnectionFactory`: + +```java +ConnectionFactory connectionFactory = ...; +R2DBCConnectionProvider provider = R2DBCConnectionProvider.from(connectionFactory); +``` + +The provider manages the connection lifecycle, automatically acquiring and +releasing connections for each operation. + +## Creating the Query Factory + +`R2DBCQueryFactory` is the main entry point for constructing queries: + +```java +R2DBCQueryFactory queryFactory = new R2DBCQueryFactory(configuration, provider); +``` + +Database-specific query factories are also available: + +- `R2DBCPostgreQueryFactory` — PostgreSQL-specific features +- `R2DBCMySQLQueryFactory` — MySQL-specific features (e.g. `INSERT IGNORE`, + `ON DUPLICATE KEY UPDATE`) +- `R2DBCServerQueryFactory` — SQL Server-specific features + +```java +R2DBCPostgreQueryFactory queryFactory = new R2DBCPostgreQueryFactory(provider); +``` + +## Querying + +Queries return reactive types from Project Reactor. + +### Fetching Multiple Results + +```java +QCustomer customer = QCustomer.customer; + +Flux lastNames = queryFactory.select(customer.lastName) + .from(customer) + .where(customer.firstName.eq("Bob")) + .fetch(); + +lastNames.subscribe(name -> System.out.println(name)); +``` + +### Fetching a Single Result + +```java +Mono bob = queryFactory.selectFrom(customer) + .where(customer.firstName.eq("Bob")) + .fetchFirst(); +``` + +### Using Tuples + +```java +Flux rows = queryFactory.select(customer.firstName, customer.lastName) + .from(customer) + .fetch(); + +rows.subscribe(row -> { + System.out.println(row.get(customer.firstName)); + System.out.println(row.get(customer.lastName)); +}); +``` + +## Joins + +Joins work the same way as in the SQL module: + +```java +QCustomer customer = QCustomer.customer; +QCompany company = QCompany.company; + +Flux results = queryFactory + .select(customer.firstName, customer.lastName, company.name) + .from(customer) + .innerJoin(customer.company, company) + .fetch(); +``` + +## Ordering and Paging + +```java +Flux results = queryFactory.selectFrom(customer) + .orderBy(customer.lastName.asc(), customer.firstName.asc()) + .limit(10) + .offset(20) + .fetch(); +``` + +## Subqueries + +```java +QCustomer customer = QCustomer.customer; +QCustomer customer2 = new QCustomer("customer2"); + +Flux results = queryFactory.select(customer.all()) + .from(customer) + .where(customer.status.eq( + SQLExpressions.select(customer2.status.max()).from(customer2))) + .fetch(); +``` + +## Data Manipulation Commands + +### Insert + +```java +QSurvey survey = QSurvey.survey; + +Mono insertCount = queryFactory.insert(survey) + .columns(survey.id, survey.name) + .values(3, "Hello") + .execute(); +``` + +Using the `set` method: + +```java +Mono insertCount = queryFactory.insert(survey) + .set(survey.id, 3) + .set(survey.name, "Hello") + .execute(); +``` + +### Update + +```java +Mono updateCount = queryFactory.update(survey) + .where(survey.name.eq("XXX")) + .set(survey.name, "S") + .execute(); +``` + +### Delete + +```java +Mono deleteCount = queryFactory.delete(survey) + .where(survey.name.eq("XXX")) + .execute(); +``` + +## MySQL-Specific Features + +The `R2DBCMySQLQueryFactory` provides MySQL-specific insert variants: + +```java +R2DBCMySQLQueryFactory mysqlFactory = new R2DBCMySQLQueryFactory(configuration, provider); + +// INSERT IGNORE +mysqlFactory.insertIgnore(survey) + .set(survey.id, 3) + .set(survey.name, "Hello") + .execute(); + +// INSERT ... ON DUPLICATE KEY UPDATE +mysqlFactory.insertOnDuplicateKeyUpdate(survey, "name = VALUES(name)") + .set(survey.id, 3) + .set(survey.name, "Hello") + .execute(); +``` + +## Comparison with the SQL Module + +| Feature | SQL Module | R2DBC Module | +|:--------|:-----------|:-------------| +| Return types | `List`, `T` | `Flux`, `Mono` | +| Connection | `java.sql.Connection` | `io.r2dbc.spi.Connection` | +| Factory class | `SQLQueryFactory` | `R2DBCQueryFactory` | +| Query class | `SQLQuery` | `R2DBCQuery` | +| Blocking | Yes | No | +| Configuration | `com.querydsl.sql.Configuration` | `com.querydsl.r2dbc.Configuration` | +| Templates | Shared `SQLTemplates` | Shared `SQLTemplates` | diff --git a/docs/tutorials/scala.md b/docs/tutorials/scala.md new file mode 100644 index 0000000000..f529d88e28 --- /dev/null +++ b/docs/tutorials/scala.md @@ -0,0 +1,214 @@ +--- +layout: default +title: Querying in Scala +parent: Tutorials +nav_order: 9 +--- + +# Querying in Scala + +Generic support for Querydsl usage in Scala is available via the +`querydsl-scala` module. + +```xml + + {{ site.group_id }} + querydsl-scala + {{ site.querydsl_version }} + +``` + +## DSL Expressions for Scala + +Querydsl for Scala provides an alternative DSL for expression construction. +The Scala DSL utilizes language features such as operator overloading, function +pointers, and implicit imports for enhanced readability and conciseness. + +Here is an overview of the main alternatives: + +``` +Standard Alternative + +expr isNotNull expr is not(null) +expr isNull expr is null +expr eq "Ben" expr === "Ben" +expr ne "Ben" expr !== "Ben" +expr append "X" expr + "X" +expr isEmpty expr is empty +expr isNotEmpty expr not empty + +// boolean +left and right left && right +left or right left || right +expr not !expr + +// comparison +expr lt 5 expr < 5 +expr loe 5 expr <= 5 +expr gt 5 expr > 5 +expr goe 5 expr >= 5 +expr notBetween(2,6) expr not between (2,6) +expr negate -expr + +// numeric +expr add 3 expr + 3 +expr subtract 3 expr - 3 +expr divide 3 expr / 3 +expr multiply 3 expr * 3 +expr mod 5 expr % 5 + +// collection +list.get(0) list(0) +map.get("X") map("X") +``` + +## Querying with SQL + +Like with Querydsl SQL for Java, you need to generate query types to construct +queries. + +Generation without bean types: + +```scala +val directory = new java.io.File("target/jdbcgen1") +val namingStrategy = new DefaultNamingStrategy() +val exporter = new MetaDataExporter() +exporter.setNamePrefix("Q") +exporter.setPackageName("com.querydsl") +exporter.setSchemaPattern("PUBLIC") +exporter.setTargetFolder(directory) +exporter.setSerializerClass(classOf[ScalaMetaDataSerializer]) +exporter.setCreateScalaSources(true) +exporter.setTypeMappings(ScalaTypeMappings.create) +exporter.export(connection.getMetaData) +``` + +Generation with bean types: + +```scala +val directory = new java.io.File("target/jdbcgen2") +val namingStrategy = new DefaultNamingStrategy() +val exporter = new MetaDataExporter() +exporter.setNamePrefix("Q") +exporter.setPackageName("com.querydsl") +exporter.setSchemaPattern("PUBLIC") +exporter.setTargetFolder(directory) +exporter.setSerializerClass(classOf[ScalaMetaDataSerializer]) +exporter.setBeanSerializerClass(classOf[ScalaBeanSerializer]) +exporter.setCreateScalaSources(true) +exporter.setTypeMappings(ScalaTypeMappings.create) +exporter.export(connection.getMetaData) +``` + +### Code Generation via Maven + +Scala sources for SQL metatypes and projections can be generated with the +`querydsl-maven-plugin`: + +```xml + + {{ site.group_id }} + querydsl-maven-plugin + {{ site.querydsl_version }} + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/test + matko + matko + com.example.schema + ${project.basedir}/src/main/scala + true + true + + + + mysql + mysql-connector-java + 5.1.16 + + + {{ site.group_id }} + querydsl-scala + {{ site.querydsl_version }} + + + org.scala-lang + scala-library + ${scala.version} + + + +``` + +The Maven goal to execute is `querydsl:export`. + +## Querying with Other Backends + +When querying with other backends the expression model has to be created +manually or alternatively the alias functionality can be used. + +Here is a minimal example with JPA: + +```scala +@Entity +class User { + @BeanProperty + @Id + var id: Integer = _ + @BeanProperty + var userName: String = _ + @BeanProperty + @ManyToOne + var department: Department = _ +} + +@Entity +class Department { + @BeanProperty + @Id + var id: Integer = _ + @BeanProperty + var name: String = _ +} +``` + +Query examples: + +```scala +val person = Person as "person" + +// List +selectFrom(person).where(person.firstName like "Rob%").fetch() + +// Unique result +selectFrom(person).where(person.firstName like "Rob%").fetchOne() + +// Long where +selectFrom(person) + .where(person.firstName like "Rob%", person.lastName like "An%") + .fetch() + +// Order +selectFrom(person).orderBy(person.firstName asc).fetch() + +// Not null +selectFrom(person) + .where(person.firstName isEmpty, person.lastName isNotNull) + .fetch() +``` + +The factory method for query creation is: + +```scala +def query() = new JPAQuery(entityManager) +``` + +Variables can be created like this: + +```scala +val person = Person as "person" +``` + +Scala support is not yet available when using Hibernate with an XML-based +configuration. `HibernateDomainExporter` currently only outputs Java source +files. diff --git a/docs/tutorials/spatial.md b/docs/tutorials/spatial.md new file mode 100644 index 0000000000..5f4437cea6 --- /dev/null +++ b/docs/tutorials/spatial.md @@ -0,0 +1,127 @@ +--- +layout: default +title: Querying Spatial +parent: Tutorials +nav_order: 7 +--- + +# Querydsl Spatial + +Support for spatial queries is available via the Querydsl Spatial module, which +is an extension module to the SQL module. The Spatial module supports the object +model of Simple Feature Access in queries and object binding. + +The [geolatte](http://www.geolatte.org/) project is used for the object model. + +![Spatial class diagram]({{ site.baseurl }}/assets/images/spatial.svg) + +## Maven Integration + +Add the following dependency to your Maven project: + +```xml + + {{ site.group_id }} + querydsl-sql-spatial + {{ site.querydsl_version }} + +``` + +Additionally, add the following database-specific extra dependencies: + +```xml + + + org.postgis + postgis-jdbc + 1.3.3 + provided + + + + + oracle + sdoapi + 11.2.0 + provided + +``` + +## Code Generation via Maven + +The code generation for Querydsl SQL can be set to detect spatial types in +database schemas and use geolatte types via the `spatial` property: + +```xml + + {{ site.group_id }} + querydsl-maven-plugin + {{ site.querydsl_version }} + ... + + ... + true + + +``` + +## Runtime Configuration + +Instead of the normal `SQLTemplates` instances, use spatial-enabled instances: + +- `GeoDBTemplates` (for H2) +- `MySQLSpatialTemplates` +- `OracleSpatialTemplates` (alpha stage) +- `PostGISTemplates` +- `SQLServer2008SpatialTemplates` +- `TeradataSpatialTemplates` + +## Querying + +With code generation and runtime configuration set for spatial types, you can +construct queries with spatial operations. + +### Filter by Distance + +```java +Geometry point = Wkt.fromWkt("Point(2 2)"); +query.where(table.geo.distance(point).lt(5.0)); +``` + +In addition to straight distance between geometries, spherical and spheroidal +distance are provided via `distanceSphere` and `distanceSpheroid`. + +### Contains + +```java +Geometry point = Wkt.fromWkt("Point(2 2)"); +query.where(table.geo.contains(point)); +``` + +### Intersection + +```java +Geometry geo = query.select(table.geo1.intersection(table.geo2)).fetchOne(); +``` + +### Access to the SPATIAL_REF_SYS Table + +Unified access to the `SPATIAL_REF_SYS` standard table is provided via the +`QSpatialRefSys` and `SpatialRefSys` classes. `SPATIAL_REF_SYS` contains data +about the supported spatial reference systems. + +```java +QSpatialRefSys spatialRefSys = QSpatialRefSys.spatialRefSys; +List referenceSystems = query.select(spatialRefSys).from(spatialRefSys).fetch(); +``` + +## Inheritance + +If you use only generic geometry types in your database schema, you can use +conversion methods in the object model to convert to more specific types: + +```java +GeometryPath geometry = shapes.geometry; +PointPath point = geometry.asPoint(); +NumberExpression pointX = point.x(); // x() is not available on GeometryExpression/GeometryPath +``` diff --git a/docs/tutorials/sql.md b/docs/tutorials/sql.md new file mode 100644 index 0000000000..76c2384945 --- /dev/null +++ b/docs/tutorials/sql.md @@ -0,0 +1,774 @@ +--- +layout: default +title: Querying SQL +parent: Tutorials +nav_order: 2 +--- + +# Querying SQL + +This chapter describes the query type generation and querying functionality of +the SQL module. + +## Maven Integration + +Add the following dependencies to your Maven project: + +```xml + + {{ site.group_id }} + querydsl-sql + {{ site.querydsl_version }} + + + + {{ site.group_id }} + querydsl-sql-codegen + {{ site.querydsl_version }} + provided + +``` + +The `querydsl-sql-codegen` dependency can be skipped if code generation happens +via Maven. + +## Code Generation via Maven + +This functionality should be primarily used via the Maven plugin: + +```xml + + {{ site.group_id }} + querydsl-maven-plugin + {{ site.querydsl_version }} + + + + export + + + + + org.apache.derby.jdbc.EmbeddedDriver + jdbc:derby:target/demoDB;create=true + com.myproject.domain + ${project.basedir}/target/generated-sources/java + + + + org.apache.derby + derby + ${derby.version} + + + +``` + +Use the goal `test-export` to treat the target folder as a test source folder. + +### Plugin Parameters + +| Name | Description | +|:-----|:------------| +| `jdbcDriver` | Class name of the JDBC driver | +| `jdbcUrl` | JDBC URL | +| `jdbcUser` | JDBC user | +| `jdbcPassword` | JDBC password | +| `namePrefix` | Name prefix for generated query classes (default: `Q`) | +| `nameSuffix` | Name suffix for generated query classes (default: empty) | +| `beanPrefix` | Name prefix for generated bean classes | +| `beanSuffix` | Name suffix for generated bean classes | +| `packageName` | Package name where source files should be generated | +| `beanPackageName` | Package name where bean files should be generated (default: `packageName`) | +| `beanInterfaces` | Array of interface class names to add to the bean classes (default: empty) | +| `beanAddToString` | Set to `true` to create a default `toString()` implementation (default: `false`) | +| `beanAddFullConstructor` | Set to `true` to create a full constructor in addition to the public empty constructor (default: `false`) | +| `beanPrintSupertype` | Set to `true` to print the supertype as well (default: `false`) | +| `schemaPattern` | Schema name pattern in LIKE form; multiple can be separated by comma (default: `null`) | +| `tableNamePattern` | Table name pattern in LIKE form; multiple can be separated by comma (default: `null`) | +| `targetFolder` | Target folder where sources should be generated | +| `beansTargetFolder` | Target folder where bean sources should be generated (defaults to `targetFolder`) | +| `namingStrategyClass` | Class name of the `NamingStrategy` (default: `DefaultNamingStrategy`) | +| `beanSerializerClass` | Class name of the `BeanSerializer` (default: `BeanSerializer`) | +| `serializerClass` | Class name of the `Serializer` (default: `MetaDataSerializer`) | +| `exportBeans` | Set to `true` to generate beans as well (default: `false`) | +| `innerClassesForKeys` | Set to `true` to generate inner classes for keys (default: `false`) | +| `validationAnnotations` | Set to `true` to enable serialization of validation annotations (default: `false`) | +| `columnAnnotations` | Export column annotations (default: `false`) | +| `createScalaSources` | Whether to export Scala sources instead of Java sources (default: `false`) | +| `schemaToPackage` | Append schema name to package (default: `false`) | +| `lowerCase` | Lower case transformation of names (default: `false`) | +| `exportTables` | Export tables (default: `true`) | +| `exportViews` | Export views (default: `true`) | +| `exportPrimaryKeys` | Export primary keys (default: `true`) | +| `tableTypesToExport` | Comma-separated list of table types to export. Overrides `exportTables` and `exportViews` if set. | +| `exportForeignKeys` | Export foreign keys (default: `true`) | +| `exportDirectForeignKeys` | Export direct foreign keys (default: `true`) | +| `exportInverseForeignKeys` | Export inverse foreign keys (default: `true`) | +| `customTypes` | Custom user types (default: none) | +| `typeMappings` | Mappings of `table.column` to Java type (default: none) | +| `numericMappings` | Mappings of size/digits to Java type (default: none) | +| `imports` | Array of Java imports added to generated query classes (default: empty) | +| `generatedAnnotationClass` | Fully qualified class name of the annotation to add on generated sources | + +Custom types can be used to register additional Type implementations: + +```xml + + com.querydsl.sql.types.InputStreamType + +``` + +Type mappings can be used to register table.column specific Java types: + +```xml + + + IMAGE
+ CONTENTS + java.io.InputStream +
+
+``` + +### Default Numeric Mappings + +| Total digits | Decimal digits | Type | +|:-------------|:---------------|:-----| +| > 18 | 0 | `BigInteger` | +| > 9 | 0 | `Long` | +| > 4 | 0 | `Integer` | +| > 2 | 0 | `Short` | +| > 0 | 0 | `Byte` | +| > 0 | > 0 | `BigDecimal` | + +Customized numeric mappings: + +```xml + + + 1 + 0 + java.lang.Byte + + +``` + +### Rename Mappings + +Schemas, tables, and columns can be renamed using the plugin: + +```xml + + + PROD + TEST + + +``` + +Renaming a table: + +```xml + + + PROD + CUSTOMER + CSTMR + + +``` + +Renaming a column: + +```xml + + + PROD + CUSTOMER + ID + IDX + + +``` + +`fromSchema` can be omitted when renaming tables and columns. + +## Creating the Query Types + +To get started, export your schema into Querydsl query types: + +```java +java.sql.Connection conn = ...; +MetaDataExporter exporter = new MetaDataExporter(); +exporter.setPackageName("com.myproject.mydomain"); +exporter.setTargetFolder(new File("target/generated-sources/java")); +exporter.export(conn.getMetaData()); +``` + +This declares that the database schema is to be mirrored into the +`com.myproject.mydomain` package in the `target/generated-sources/java` folder. + +The generated types have the table name transformed to mixed case as the class +name and a similar mixed case transformation applied to the columns which are +available as property paths in the query type. + +In addition, primary key and foreign key constraints are provided as fields +which can be used for compact join declarations. + +## Configuration + +The configuration is done via `com.querydsl.sql.Configuration` which takes a +Querydsl SQL dialect as an argument. For H2: + +```java +SQLTemplates templates = new H2Templates(); +Configuration configuration = new Configuration(templates); +``` + +Querydsl uses SQL dialects to customize the SQL serialization needed for +different relational databases. The available dialects are: + +- `CUBRIDTemplates` +- `DB2Templates` +- `DerbyTemplates` +- `FirebirdTemplates` +- `HSQLDBTemplates` +- `H2Templates` +- `MySQLTemplates` +- `OracleTemplates` +- `PostgreSQLTemplates` +- `SQLiteTemplates` +- `SQLServerTemplates` +- `SQLServer2005Templates` +- `SQLServer2008Templates` +- `SQLServer2012Templates` +- `TeradataTemplates` + +For customized `SQLTemplates` instances, use the builder pattern: + +```java +H2Templates.builder() + .printSchema() // include the schema in the output + .quote() // quote names + .newLineToSingleSpace() // replace new lines with single space + .escape(ch) // set the escape char + .build(); // get the customized SQLTemplates instance +``` + +The methods of the `Configuration` class can be used to enable direct +serialization of literals via `setUseLiterals(true)`, override schema and +tables, and register custom types. See the Javadocs for full details. + +## Querying + +For the following examples we use the `SQLQueryFactory` class for query +creation: + +```java +SQLQueryFactory queryFactory = new SQLQueryFactory(configuration, dataSource); +``` + +Querying with Querydsl SQL: + +```java +QCustomer customer = new QCustomer("c"); + +List lastNames = queryFactory.select(customer.lastName).from(customer) + .where(customer.firstName.eq("Bob")) + .fetch(); +``` + +This is transformed into the following SQL, assuming the related table name is +`customer` and the columns `first_name` and `last_name`: + +```sql +SELECT c.last_name +FROM customer c +WHERE c.first_name = 'Bob' +``` + +## General Usage + +Use the cascading methods of the `SQLQuery` class: + +- **select:** Set the projection of the query. (Not necessary if created via + query factory) +- **from:** Add query sources. +- **innerJoin, join, leftJoin, rightJoin, fullJoin, on:** Add join elements. + For join methods, the first argument is the join source and the second the + target (alias). +- **where:** Add query filters, either in varargs form separated via commas or + cascaded via the `and` operator. +- **groupBy:** Add group by arguments in varargs form. +- **having:** Add having filter of the "group by" grouping as a varargs array + of Predicate expressions. +- **orderBy:** Add ordering of the result as a varargs array of order + expressions. Use `asc()` and `desc()` on numeric, string, and other + comparable expressions to access `OrderSpecifier` instances. +- **limit, offset, restrict:** Set the paging of the result. `limit` for max + results, `offset` for skipping rows, and `restrict` for defining both in one + call. + +## Joins + +Joins are constructed using the following syntax: + +```java +QCustomer customer = QCustomer.customer; +QCompany company = QCompany.company; +queryFactory.select(customer.firstName, customer.lastName, company.name) + .from(customer) + .innerJoin(customer.company, company) + .fetch(); +``` + +For a left join: + +```java +queryFactory.select(customer.firstName, customer.lastName, company.name) + .from(customer) + .leftJoin(customer.company, company) + .fetch(); +``` + +Alternatively, the join condition can be written out: + +```java +queryFactory.select(customer.firstName, customer.lastName, company.name) + .from(customer) + .leftJoin(company).on(customer.company.eq(company)) + .fetch(); +``` + +## Ordering + +```java +queryFactory.select(customer.firstName, customer.lastName) + .from(customer) + .orderBy(customer.lastName.asc(), customer.firstName.asc()) + .fetch(); +``` + +Equivalent SQL: + +```sql +SELECT c.first_name, c.last_name +FROM customer c +ORDER BY c.last_name ASC, c.first_name ASC +``` + +## Grouping + +```java +queryFactory.select(customer.lastName) + .from(customer) + .groupBy(customer.lastName) + .fetch(); +``` + +Equivalent SQL: + +```sql +SELECT c.last_name +FROM customer c +GROUP BY c.last_name +``` + +## Using Subqueries + +To create a subquery, use one of the factory methods of `SQLExpressions` and +add the query parameters via `from`, `where`, etc. + +```java +QCustomer customer = QCustomer.customer; +QCustomer customer2 = new QCustomer("customer2"); +queryFactory.select(customer.all()) + .from(customer) + .where(customer.status.eq( + SQLExpressions.select(customer2.status.max()).from(customer2))) + .fetch(); +``` + +Another example: + +```java +QStatus status = QStatus.status; +queryFactory.select(customer.all()) + .from(customer) + .where(customer.status.in( + SQLExpressions.select(status.id).from(status).where(status.level.lt(3)))) + .fetch(); +``` + +## Selecting Literals + +To select literals, create constant instances: + +```java +queryFactory.select(Expressions.constant(1), + Expressions.constant("abc")); +``` + +The class `com.querydsl.core.types.dsl.Expressions` also offers other useful +static methods for projections, operations, and template creation. + +## Query Extension Support + +Custom query extensions to support engine-specific syntax can be created by +subclassing `AbstractSQLQuery` and adding flagging methods like in this +`MySQLQuery` example: + +```java +public class MySQLQuery extends AbstractSQLQuery> { + + public MySQLQuery(Connection conn) { + this(conn, new MySQLTemplates(), new DefaultQueryMetadata()); + } + + public MySQLQuery(Connection conn, SQLTemplates templates) { + this(conn, templates, new DefaultQueryMetadata()); + } + + protected MySQLQuery(Connection conn, SQLTemplates templates, QueryMetadata metadata) { + super(conn, new Configuration(templates), metadata); + } + + public MySQLQuery bigResult() { + return addFlag(Position.AFTER_SELECT, "SQL_BIG_RESULT "); + } + + public MySQLQuery bufferResult() { + return addFlag(Position.AFTER_SELECT, "SQL_BUFFER_RESULT "); + } + + // ... +} +``` + +The flags are custom SQL snippets that can be inserted at specific points in +the serialization. The supported positions are the enums of the +`com.querydsl.core.QueryFlag.Position` enum class. + +## Window Functions + +Window functions are supported via the methods in the `SQLExpressions` class: + +```java +queryFactory.select(SQLExpressions.rowNumber() + .over() + .partitionBy(employee.name) + .orderBy(employee.id)) + .from(employee) +``` + +## Common Table Expressions + +Common table expressions are supported via two syntax variants: + +```java +QEmployee employee = QEmployee.employee; +queryFactory.with(employee, SQLExpressions.select(employee.all) + .from(employee) + .where(employee.name.startsWith("A"))) + .from(...) +``` + +Using a column listing: + +```java +QEmployee employee = QEmployee.employee; +queryFactory.with(employee, employee.id, employee.name) + .as(SQLExpressions.select(employee.id, employee.name) + .from(employee) + .where(employee.name.startsWith("A"))) + .from(...) +``` + +If the columns of the common table expression are a subset of an existing table +or view, use a generated path type for it (e.g. `QEmployee`). Otherwise, use +`PathBuilder`: + +```java +QEmployee employee = QEmployee.employee; +QDepartment department = QDepartment.department; +PathBuilder emp = new PathBuilder(Tuple.class, "emp"); +queryFactory.with(emp, SQLExpressions.select(employee.id, employee.name, employee.departmentId, + department.name.as("departmentName")) + .from(employee) + .innerJoin(department).on(employee.departmentId.eq(department.id))) + .from(...) +``` + +## Data Manipulation Commands + +### Insert + +With columns: + +```java +QSurvey survey = QSurvey.survey; + +queryFactory.insert(survey) + .columns(survey.id, survey.name) + .values(3, "Hello").execute(); +``` + +Without columns: + +```java +queryFactory.insert(survey) + .values(4, "Hello").execute(); +``` + +With subquery: + +```java +queryFactory.insert(survey) + .columns(survey.id, survey.name) + .select(SQLExpressions.select(survey2.id.add(1), survey2.name).from(survey2)) + .execute(); +``` + +Using the `set` method: + +```java +QSurvey survey = QSurvey.survey; + +queryFactory.insert(survey) + .set(survey.id, 3) + .set(survey.name, "Hello").execute(); +``` + +The `set` method always expands internally to columns and values. + +To get the created keys instead of the modified rows count, use +`executeWithKey` / `executeWithKeys`. + +To populate a clause based on the contents of a bean: + +```java +queryFactory.insert(survey) + .populate(surveyBean).execute(); +``` + +This excludes null bindings. To include null bindings: + +```java +queryFactory.insert(survey) + .populate(surveyBean, DefaultMapper.WITH_NULL_BINDINGS).execute(); +``` + +### Update + +With where: + +```java +QSurvey survey = QSurvey.survey; + +queryFactory.update(survey) + .where(survey.name.eq("XXX")) + .set(survey.name, "S") + .execute(); +``` + +Without where: + +```java +queryFactory.update(survey) + .set(survey.name, "S") + .execute(); +``` + +Using bean population: + +```java +queryFactory.update(survey) + .populate(surveyBean) + .execute(); +``` + +### Delete + +With where: + +```java +QSurvey survey = QSurvey.survey; + +queryFactory.delete(survey) + .where(survey.name.eq("XXX")) + .execute(); +``` + +Without where: + +```java +queryFactory.delete(survey) + .execute(); +``` + +## Batch Support in DML Clauses + +Querydsl SQL supports JDBC batch updates through the DML APIs. Bundle +consecutive DML calls with a similar structure via `addBatch()`: + +Update: + +```java +QSurvey survey = QSurvey.survey; + +queryFactory.insert(survey).values(2, "A").execute(); +queryFactory.insert(survey).values(3, "B").execute(); + +SQLUpdateClause update = queryFactory.update(survey); +update.set(survey.name, "AA").where(survey.name.eq("A")).addBatch(); +update.set(survey.name, "BB").where(survey.name.eq("B")).addBatch(); +``` + +Delete: + +```java +SQLDeleteClause delete = queryFactory.delete(survey); +delete.where(survey.name.eq("A")).addBatch(); +delete.where(survey.name.eq("B")).addBatch(); +delete.execute(); +``` + +Insert: + +```java +SQLInsertClause insert = queryFactory.insert(survey); +insert.set(survey.id, 5).set(survey.name, "5").addBatch(); +insert.set(survey.id, 6).set(survey.name, "6").addBatch(); +insert.execute(); +``` + +## Bean Class Generation + +To create JavaBean DTO types for the tables of your schema: + +```java +java.sql.Connection conn = ...; +MetaDataExporter exporter = new MetaDataExporter(); +exporter.setPackageName("com.myproject.mydomain"); +exporter.setTargetFolder(new File("src/main/java")); +exporter.setBeanSerializer(new BeanSerializer()); +exporter.export(conn.getMetaData()); +``` + +Now you can use the bean types as arguments to the `populate` method in DML +clauses and you can project directly to bean types in queries: + +```java +QEmployee e = new QEmployee("e"); + +// Insert +Employee employee = new Employee(); +employee.setFirstname("John"); +Integer id = queryFactory.insert(e).populate(employee).executeWithKey(e.id); +employee.setId(id); + +// Update +employee.setLastname("Smith"); +queryFactory.update(e).populate(employee).where(e.id.eq(employee.getId())).execute(); + +// Query +Employee smith = queryFactory.selectFrom(e).where(e.lastname.eq("Smith")).fetchOne(); + +// Delete +queryFactory.delete(e).where(e.id.eq(employee.getId())).execute(); +``` + +## Extracting the SQL Query and Bindings + +The SQL query and bindings can be extracted via `getSQL`: + +```java +SQLBindings bindings = query.getSQL(); +System.out.println(bindings.getSQL()); +``` + +To include all literals in the SQL string, enable literal serialization on the +query or configuration level via `setUseLiterals(true)`. + +## Custom Types + +Querydsl SQL provides the possibility to declare custom type mappings for +`ResultSet`/`Statement` interaction. Custom type mappings can be declared in +`Configuration` instances: + +```java +Configuration configuration = new Configuration(new H2Templates()); +// overrides the mapping for Types.DATE +configuration.register(new UtilDateType()); +``` + +For a table column: + +```java +Configuration configuration = new Configuration(new H2Templates()); +// declares a mapping for the gender column in the person table +configuration.register("person", "gender", new EnumByNameType(Gender.class)); +``` + +To customize a numeric mapping: + +```java +configuration.registerNumeric(5, 2, Float.class); +``` + +This maps the `Float` type to the `NUMERIC(5,2)` type. + +## Listening to Queries and Clauses + +`SQLListener` is a listener interface that can be used to listen to queries and +DML clauses. `SQLListener` instances can be registered on the configuration or +on individual query/clause instances via the `addListener` method. + +Use cases for listeners include data synchronization, logging, caching, and +validation. + +## Spring Integration + +Querydsl SQL integrates with Spring through the `querydsl-sql-spring` module: + +```xml + + {{ site.group_id }} + querydsl-sql-spring + {{ site.querydsl_version }} + +``` + +It provides Spring exception translation and a Spring connection provider for +usage of Querydsl SQL with Spring transaction managers: + +```java +@Configuration +public class JdbcConfiguration { + + @Bean + public DataSource dataSource() { + // implementation omitted + } + + @Bean + public PlatformTransactionManager transactionManager() { + return new DataSourceTransactionManager(dataSource()); + } + + @Bean + public com.querydsl.sql.Configuration querydslConfiguration() { + SQLTemplates templates = H2Templates.builder().build(); + com.querydsl.sql.Configuration configuration = new com.querydsl.sql.Configuration(templates); + configuration.setExceptionTranslator(new SpringExceptionTranslator()); + return configuration; + } + + @Bean + public SQLQueryFactory queryFactory() { + SpringConnectionProvider provider = new SpringConnectionProvider(dataSource()); + return new SQLQueryFactory(querydslConfiguration(), provider); + } +} +``` diff --git a/pom.xml b/pom.xml index f2963be2ca..5c868b834a 100644 --- a/pom.xml +++ b/pom.xml @@ -765,13 +765,6 @@ - - docs - - querydsl-docs - - - examples diff --git a/querydsl-docs/etc/jpa2_comparison.txt b/querydsl-docs/etc/jpa2_comparison.txt deleted file mode 100644 index c104938f5d..0000000000 --- a/querydsl-docs/etc/jpa2_comparison.txt +++ /dev/null @@ -1,279 +0,0 @@ -Below is a comparison of JPA 2 Criteria and Querydsl HQL queries. - -The purpose of this comparison is to show the benefits of using a dynamic metamodel like the Querydsl metamodel compared to a static metamodel like the JPA 2 Criteria metamodel. - -Feel free to ask for more JPA 2 -> Querydsl translations in the comments of this post. - -The differences of the metamodels themselves are not discussed here. Both Querydsl and JPA 2 use APT for metamodel generation, so the configuration -overhead is comparable. - - -[b]Selecting an entity[/b] - -[code] -CriteriaQuery criteria = builder.createQuery( Person.class ); -Root personRoot = criteria.from( Person.class ); -criteria.select( personRoot ); -criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) ); -List people = em.createQuery( criteria ).getResultList(); -[/code] - -becomes - -[code] -JPAQuery query = new JPAQuery(em); -QPerson person = QPerson.person; -List people = query.from(person).where(person.eyeColor.eq("brown")) - .list(person); -[/code] - - -[b]Selecting an attribute[/b] - -[code] -CriteriaQuery criteria = builder.createQuery( Integer.class ); -Root personRoot = criteria.from( Person.class ); -criteria.select( personRoot.get( Person_.age ) ); -criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) ); -List ages = em.createQuery( criteria ).getResultList(); -[/code] - -becomes - -[code] -JPAQuery query = new JPAQuery(em); -QPerson person = QPerson.person; -List ages = query.from(person).where(person.eyeColor.eq("brown")) - .list(person.age); -[/code] - - -[b]Select an expression[/b] - - -[code] -CriteriaQuery criteria = builder.createQuery( Integer.class ); -Root personRoot = criteria.from( Person.class ); -criteria.select( builder.max( personRoot.get( Person_.age ) ) ); -criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) ); -Integer maxAge = em.createQuery( criteria ).getSingleResult(); -[/code] - -becomes - -[code] -JPAQuery query = new JPAQuery(em); -QPerson person = QPerson.person; -Integer maxAge = query.from(person) - .where(person.eyeColor.eq("brown")) - .uniqueResult(person.age.max()); -[/code] - -[b]Selecting an array[/b] - -[code] -CriteriaQuery criteria = builder.createQuery( Object[].class ); -Root personRoot = criteria.from( Person.class ); -Path idPath = personRoot.get( Person_.id ); -Path agePath = personRoot.get( Person_.age ); -criteria.select( builder.array( idPath, agePath ) ); -criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) ); -List valueArray = em.createQuery( criteria ).getResultList(); -[/code] - -becomes - -[code] -JPAQuery query = new JPAQuery(em); -QPerson person = QPerson.person; -List valueArray = query.from(person) - .where(person.eyeColor.eq("brown")) - .list(person.id, person.age); -[/code] - - -[b]Selecting an array (2)[/b] - -[code] -CriteriaQuery criteria = builder.createQuery( Object[].class ); -Root personRoot = criteria.from( Person.class ); -Path idPath = personRoot.get( Person_.id ); -Path agePath = personRoot.get( Person_.age ); -criteria.multiselect( idPath, agePath ); -criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) ); -List valueArray = em.createQuery( criteria ).getResultList(); -[/code] - -becomes - -[code] -JPAQuery query = new JPAQuery(em); -QPerson person = QPerson.person; -List valueArray = query.from(person) - .where(person.eyeColor.eq("brown")) - .list(person.id, person.age); -[/code] - -[b]Selecting an wrapper[/b] - -[code] -CriteriaQuery criteria = builder.createQuery( PersonWrapper.class); -Root personRoot = criteria.from( Person.class ); -criteria.select( - builder.construct( - PersonWrapper.class, - personRoot.get( Person_.id ), - personRoot.get( Person_.age ) - )); -criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) ); -List people = em.createQuery( criteria ).getResultList(); -[/code] - -becomes - -[code] -JPAQuery query = new JPAQuery(em); -QPerson person = QPerson.person; -List people = query.from(person) - .where(person.eyeColor.eq("brown")) - .list(new QPersonWrapper(person.id, person.age)) -[/code] - -[b]Selecting a tuple[/b] - -[code] -CriteriaQuery criteria = builder.createTupleQuery(); -Root personRoot = criteria.from( Person.class ); -Path idPath = personRoot.get( Person_.id ); -Path agePath = personRoot.get( Person_.age ); -criteria.multiselect( idPath, agePath ); -criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) ); -List tuples = em.createQuery( criteria ).getResultList(); -[/code] - -Not supported in Querydsl. Feel free to provide snippets how this could be done. - - -[b]Using parameters[/b] - -[code] -CriteriaQuery criteria = builder.createQuery( Person.class ); -Root personRoot = criteria.from( Person.class ); -criteria.select( personRoot ); -ParameterExpression eyeColorParam = builder.parameter( String.class ); -criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), eyeColorParam ) ); -TypedQuery query = em.createQuery( criteria ); -query.setParameter( eyeColorParam, "brown" ); -List people = em.createQuery( query).getResultList(); -[/code] - -becomes - -[code] -JPAQuery query = new JPAQuery(em); -QPerson person = QPerson.person; -List people = query.from(person) - .where(person.eyeColor.eq("brown")) - .list(person); -[/code] - - -[b]Multiple roots[/b] - -[code] -CriteriaQuery query = builder.createQuery(); -Root men = query.from( Person.class ); -Root 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 ) ); -[/code] - -becomes - -[code] -JPAQuery query = new JPAQuery(em); -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)); -[/code] - -[b]Fetch joins[/b] - -[code] -CriteriaQuery query = builder.createQuery(Employee.class); -Root emp = query.from(Employee.class); -emp.fetch("address"); -query.select(emp); -List employees = em.createQuery( query).getResultList(); -[/code] - -becomes - -[code] -JPAQuery query = new JPAQuery(em); -QEmployee employee = QEmployee.employee; -List employees = query.from(employee).join(employee.address).fetch() - .list(employee); -[/code] - -[b]Left join[/b] - -[code] -CriteriaQuery query = builder.createQuery(Employee.class); -Root emp = query.from(Employee.class); -emp.fetch(Employee_.phones, JoinType.LEFT); -query.select(emp).distinct(true); -List employees = em.createQuery( query).getResultList(); -[/code] - -becomes - -[code] -JPAQuery query = new JPAQuery(em); -QEmployee employee = QEmployee.employee; -List employees = query.from(employee) - .leftJoin(employee.phones).fetch() - .listDistinct(employee); -[/code] - -[b]Subquery[/b] - -[code] -CriteriaQuery query = builder.createQuery(Employee.class); -Root emp = query.from(Employee.class); -Subquery sq = query.subquery(Project.class); -Root project sq.from(Project.class); -Join sqEmp = project.join(Project_.employees); -sq.select(project) - .where(cb.equals(sqEmp, emp), - cb.equals(project.get(Project_.name), - cb.parameter(String.class,"project"))); -criteria.add(cb.exists()); -[/code] - -becomes - -[code] -JPAQuery query = new JPAQuery(em); -QEmployee employee = QEmployee.employee; -QEmployee emp = new QEmployee("emp"); -QProject project = QProject.project; -query.from(employee).where( - new HQLSubQuery().from(project).join(project.employees, emp) - .where(emp.eq(employee), project.name.eq("some name")) - .list(project).exists() - ).list(employee); -[/code] diff --git a/querydsl-docs/pom.xml b/querydsl-docs/pom.xml deleted file mode 100644 index 3da6cb7533..0000000000 --- a/querydsl-docs/pom.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - 4.0.0 - - - io.github.openfeign.querydsl - querydsl-root - 7.2-SNAPSHOT - - - querydsl-docs - Querydsl - Documentation - jdocbook - - - en-US - http://docbook.sourceforge.net/release/xsl/current/highlighting/xslthl-config.xml - - - - - - org.jboss.maven.plugins - maven-jdocbook-plugin - 2.3.10 - true - - ${translation} - Querydsl_Reference.xml - - ${basedir}/src/main/docbook - - *.xml - **/*.xml - - - - - html - index.html - file:${basedir}/src/main/styles/html/custom.xsl - - - html_single - index.html - file:${basedir}/src/main/styles/html_single/custom.xsl - - - pdf - file:${basedir}/src/main/styles/pdf/custom.xsl - - - - true - true - - - - - net.sf.xslthl - xslthl - 2.1.3 - - - - - - - diff --git a/querydsl-docs/src/main/docbook/css/highlight.css b/querydsl-docs/src/main/docbook/css/highlight.css deleted file mode 100644 index 7efd8fd13a..0000000000 --- a/querydsl-docs/src/main/docbook/css/highlight.css +++ /dev/null @@ -1,39 +0,0 @@ -/* - code highlight CSS resembling the Eclipse IDE default color schema - @author Costin Leau -*/ - -.hl-keyword { - color: #7F0055; - font-weight: bold; -} - -.hl-comment { - color: #3F5F5F; - font-style: italic; -} - -.hl-multiline-comment { - color: #3F5FBF; - font-style: italic; -} - -.hl-tag { - color: #3F7F7F; -} - -.hl-attribute { - color: #7F007F; -} - -.hl-value { - color: #2A00FF; -} - -.hl-string { - color: #2A00FF; -} - -.hl-annotation { - font-style: normal; -} diff --git a/querydsl-docs/src/main/docbook/css/stylesheet.css b/querydsl-docs/src/main/docbook/css/stylesheet.css deleted file mode 100644 index 5955cb2a3e..0000000000 --- a/querydsl-docs/src/main/docbook/css/stylesheet.css +++ /dev/null @@ -1,204 +0,0 @@ -@import url("highlight.css"); - -html { - padding: 0pt; - margin: 0pt; -} - -body { - color: #333333; - font-family: Arial, Sans-serif; - margin: 15px 30px; - display: block; -} - -div.book { - margin-top: 5em; - margin-left: 10%; - margin-right: 10%; -} - -div { - margin: 0pt; -} - -p { - text-align: justify; -} - -hr { - border: 1px solid #CCCCCC; - background: #CCCCCC; -} - -h1,h2,h3,h4,h5,h6 { - color: #000000; - cursor: text; - font-weight: bold; - margin: 30px 0 10px; - padding: 0; -} - -h1,h2,h3 { - margin: 40px 0 10px; -} - -h1 { - margin: 70px 0 30px; - padding-top: 20px; -} - -div.part h1 { - border-top: 1px dotted #CCCCCC; -} - -h1,h1 code { - font-size: 32px; -} - -h2,h2 code { - font-size: 24px; -} - -h3,h3 code { - font-size: 20px; -} - -h4,h1 code,h5,h5 code,h6,h6 code { - font-size: 18px; -} - -pre { - line-height: 1.0; - /*color: black;*/ -} - -pre.programlisting { - font-size: 10pt; - padding: 6pt 10pt; - border: 1px solid #CCCCCC; - border-radius: 3px 3px 3px 3px; - background: #f8f8f8; - clear: both; -} - -div.table { - margin: 1em; - padding: 0.5em; - text-align: center; -} - -div.table table { - display: table; - width: 100%; -} - -div.table td { - padding-left: 7px; - padding-right: 7px; -} - -.sidebar { - float: right; - margin: 10px 0 10px 30px; - padding: 10px 20px 20px 20px; - width: 33%; - border: 1px solid black; - background-color: #F4F4F4; - font-size: 14px; -} - -.mediaobject { - padding-top: 30px; - padding-bottom: 30px; -} - -.legalnotice { - font-family: Verdana, Arial, helvetica, sans-serif; - font-size: 12px; - font-style: italic; -} - -p.releaseinfo { - font-size: 100%; - font-weight: bold; - font-family: Verdana, Arial, helvetica, sans-serif; - padding-top: 10px; -} - -p.pubdate { - font-size: 120%; - font-weight: bold; - font-family: Verdana, Arial, helvetica, sans-serif; -} - -span.productname { - font-size: 200%; - font-weight: bold; - font-family: Verdana, Arial, helvetica, sans-serif; -} - -.code { - font-size: 14px; - /*color: 0000C0;*/ -} - -div.table td, div.table th { - padding: 7px; -} - -a { - text-decoration: none; - color: #4183C4; -} - -/* toc font sizes */ - -div.toc { - line-height: 1.2; -} - -dl,dt { - margin-top: 1px; - margin-bottom: 0; -} - -div.toc>dl>dt { - font-size: 32px; - font-weight: bold; - margin: 30px 0 10px 0; - display: block; -} - -div.toc>dl>dd>dl>dt { - font-size: 24px; - font-weight: bold; - margin: 20px 0 10px 0; - display: block; -} - -div.toc>dl>dd>dl>dd>dl>dt { - font-weight: bold; - font-size: 20px; - margin: 10px 0 0 0; -} - -/* authorgroup */ - -.authorgroup .author { - display: inline; -} - -.authorgroup .author h3 { - font-size: 1em; - font-weight: normal; - display: inline; -} - -.authorgroup > .author:before { - content: ", "; -} - -.authorgroup > .author:first-child:before { - content: ""; -} \ No newline at end of file diff --git a/querydsl-docs/src/main/docbook/en-US/Querydsl_Reference.xml b/querydsl-docs/src/main/docbook/en-US/Querydsl_Reference.xml deleted file mode 100644 index 52591299b7..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/Querydsl_Reference.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - -]> - - - Querydsl Reference Guide - - Querydsl - &versionNumber; - - - Timo - Westkämper - - - Samppa - Saarela - - - Vesa - Marttila - - - Lassi - Immonen - - - Ruben - Dijkstra - - - John - Tims - - - Robert - Bain - - - Ido - Salomon - - - Jan-Willem - Gmelig Meyling - - - - - - - - - - - - - ©rightYear; - ©rightHolder; - - - - - - - - - - - - - - - diff --git a/querydsl-docs/src/main/docbook/en-US/content/general.xml b/querydsl-docs/src/main/docbook/en-US/content/general.xml deleted file mode 100644 index 52e7c5b8b4..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/general.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - General usage - - - The General usage section covers aspects that are not covered in the tutorial section of the reference documentation. - It follows a use case oriented structure. - - - - - - - - \ No newline at end of file diff --git a/querydsl-docs/src/main/docbook/en-US/content/general/alias.xml b/querydsl-docs/src/main/docbook/en-US/content/general/alias.xml deleted file mode 100644 index 7c057de9cc..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/general/alias.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - Alias usage - - - In cases where code generation is not an option, alias objects can be used as path - references for expression construction. They can be used via proxied Java Bean objects - through getter method invocations. - - - - The following examples demonstrate how alias objects can be used as replacements - for expression creation based on generated types. - - - - At first an example query with APT generated domain types: - - - - - - And now with an alias instance for the Cat class. The call c.getKittens() inside - the dollar-method is internally transformed into the property path c.kittens. - - - - - - To use the alias functionality in your code, add the following two - imports - - - - - - The following example is a variation of the previous, where the access to the list - size happens inside the dollar-method invocation. - - - - - - All non-primitive and non-final typed properties of aliases are aliases - themselves. So you may cascade method calls until you hit a primitive or final type - in the dollar-method scope. e.g. - - - - - - is transformed into *c.mate.name* internally, but - - - - - - is not transformed properly, since the toLowerCase() invocation is not tracked. - - - - Note also that you may only invoke getters, size(), contains(Object) and get(int) - on alias types. All other invocations throw exceptions. - - - - diff --git a/querydsl-docs/src/main/docbook/en-US/content/general/codegen.xml b/querydsl-docs/src/main/docbook/en-US/content/general/codegen.xml deleted file mode 100644 index 7a34e4ba4a..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/general/codegen.xml +++ /dev/null @@ -1,832 +0,0 @@ - - - Code generation - - The Java 6 APT annotation processing functionality is used in Querydsl for code - generation in the JPA, JDO and Mongodb modules. This section describes various configuration - options for the code generation and an alternative to APT usage. - - - - Path initialization - - - By default Querydsl initializes only reference properties of the first two levels. In cases where - longer initialization paths are required, these have to be annotated in the domain - types via - com.querydsl.core.annotations.QueryInit - annotations. QueryInit is used on properties where deep initializations are - needed. The following example demonstrates the usage. - - - - - - This example enforces the initialization of the account.customer path, when an - Event path is initialized as a root path / variable. The path initialization - format supports wildcards as well, e.g. "customer.*" or just "*". - - - - The automatic path initialization replaces the manual one, which - required the entity fields to be non-final. The declarative format has the benefit - to be applied to all top level instances of a Query type and to enable the usage - of final entity fields. - - - - Automatic path initialization is the preferred initialization strategy, but - manual initialization can be activated via the Config annotation, which is - described below. - - - - - - Customization - - - The serialization of Querydsl can be customized via Config annotations on - packages and types. They customize the serialization of the annotated package or type. - - - - The serialization options are - - - - Config options - - - - - - Name - Description - - - - - entityAccessors - accessor methods for entity paths instead of public final fields (default: false) - - - listAccessors - listProperty(int index) style methods (default: false) - - - mapAccessors - mapProperty(Key key) style accessor methods (default: false) - - - createDefaultVariable - generate the default variable (default: true) - - - defaultVariableName - name of the default variable - - - -
- - Below are some examples. - - Customization of Entity type serialization: - - - - Customization of package content: - - - - - - - If you want to customize the serializer configuration globally, - you can do this via the following APT options - - - - APT options - - - - - - Name - Description - - - - - querydsl.entityAccessors - enable reference field accessors - - - querydsl.listAccessors - enable accessors for direct indexed list access - - - querydsl.mapAccessors - enable accessors for direct key based map access - - - querydsl.prefix - override the prefix for query types(default: Q) - - - querydsl.suffix - set a suffix for query types - - - querydsl.packageSuffix - set a suffix for query type packages - - - querydsl.createDefaultVariable - set whether default variables are created - - - querydsl.unknownAsEmbeddable - set where unknown non-annotated classes should be treated as embeddable (default: - false) - - - - querydsl.includedPackages - comma separated list of packages to be included into code generation (default: all) - - - - querydsl.includedClasses - comma separated list of class names to be included into code generation (default: all) - - - - querydsl.excludedPackages - comma separated list of packages to be excluded from code generation (default: none) - - - - querydsl.excludedClasses - comma separated list of class names to be excluded from code generation (default: none) - - - - querydsl.useFields - set whether fields are used as metadata source (default: true) - - - querydsl.useGetters - set whether accessors are used as metadata source (default: true) - - - querydsl.generatedAnnotationClass - - The fully qualified class name of the Single-Element Annotation (with - String element) to be added on the generated sources. Build in - com.querydsl.core.annotations.Generatedhas CLASS retention which can be - used for byte code analysis tools like Jacoco. - (default: javax.annotation.Generated or - javax.annotation.processing.Generated - depending on the java version). See also - - Single-Element Annotation - - - - - -
- - Using the Maven APT plugin this works for example like this: - - - - - - ... - - com.mysema.maven - apt-maven-plugin - 1.1.3 - - - - process - - - target/generated-sources/java - com.querydsl.apt.jpa.JPAAnnotationProcessor - - true - false - - - - - - ... - - -
-]]> - - - Alternatively maven-compiler-plugin can be configured - to hook APT directly into compilation: - - - - - - ... - - maven-compiler-plugin - - target/generated-sources/java - - -Aquerydsl.entityAccessors=true - -Aquerydsl.useFields=false - - - - - io.github.openfeign.querydsl - querydsl-apt - ${querydsl.version} - jpa - - - org.hibernate.jakarta.persistence - hibernate-jpa-2.1-api - 1.0.0.Final - - - - ... - - -
-]]> - - - Notice that you need to use a proper classifier when defining dependency - to io.github.openfeign.querydsl:querydsl-apt. Those additional artifacts - define the annotation processor to be used in - META-INF/services/javax.annotation.processing.Processor. - - - Available classifiers include: - - - - general - - - hibernate - - - jdo - - - jpa - - - - - With this configuration query objects can have their sources generated - and compiled during compilation of the domain objects. This will also - automatically add the generated sources directory to Maven project - source roots. - - - - The great advantage of this approach is that it can also handle - annotated Groovy classes using groovy-eclipse compiler: - - - - - - ... - - maven-compiler-plugin - - groovy-eclipse-compiler - target/generated-sources/java - - -Aquerydsl.entityAccessors=true - -Aquerydsl.useFields=false - - - - - org.codehaus.groovy - groovy-eclipse-compiler - 2.9.1-01 - - - org.codehaus.groovy - groovy-eclipse-batch - 2.3.7-01 - - - io.github.openfeign.querydsl - querydsl-apt - ${querydsl.version} - jpa - - - org.hibernate.jakarta.persistence - hibernate-jpa-2.1-api - 1.0.0.Final - - - - ... - - - -]]> - - - - - Custom type mappings - - - Custom type mappings can be used on properties to override the derived Path - type. This can be useful for example in cases where comparison and String operations should - be blocked on certain String paths or Date / Time support for - custom types needs to be added. Support for Date / Time types of the Joda time API - and JDK (java.util.Date, Calendar and subtypes) is built in, but other APIs might need - to be supported using this feature. - - - The following example demonstrates the usage: - - - - The value PropertyType.NONE can be used to skip a property in the - query type generation. This case is different from @Transient or @QueryTransient - annotated properties, where properties are not persisted. PropertyType.NONE just - omits the property from the Querydsl query type. - - - - - - Delegate methods - - To declare a static method as a delegate method add the QueryDelegate - annotation with the corresponding domain type as a value and provide a method - signature that takes the corresponding Querydsl query type as the first argument. - - - Here is a simple example from a unit test: - - - - - - And the generated methods in the QUser query type: - - - - Delegate methods can also be used to extend built-in types. - Here are some examples - - - date, Pair period) { - return date.goe(period.getFirst()).and(date.loe(period.getSecond())); - } - - @QueryDelegate(Timestamp.class) - public static BooleanExpression inDatePeriod(DateTimePath timestamp, Pair period) { - Timestamp first = new Timestamp(DateUtils.truncate(period.getFirst(), Calendar.DAY_OF_MONTH).getTime()); - Calendar second = Calendar.getInstance(); - second.setTime(DateUtils.truncate(period.getSecond(), Calendar.DAY_OF_MONTH)); - second.add(1, Calendar.DAY_OF_MONTH); - return timestamp.goe(first).and(timestamp.lt(new Timestamp(second.getTimeInMillis()))); - } - -} -]]> - - When delegate methods are declared for builtin types then subclasses with the - proper delegate method usages are created: - - - { - - public QDate(BeanPath entity) { - super(entity.getType(), entity.getMetadata()); - } - - public QDate(PathMetadata metadata) { - super(java.sql.Date.class, metadata); - } - - public BooleanExpression inPeriod(com.mysema.commons.lang.Pair period) { - return QueryExtensions.inPeriod(this, period); - } - -} - -public class QTimestamp extends DateTimePath { - - public QTimestamp(BeanPath entity) { - super(entity.getType(), entity.getMetadata()); - } - - public QTimestamp(PathMetadata metadata) { - super(java.sql.Timestamp.class, metadata); - } - - public BooleanExpression inDatePeriod(com.mysema.commons.lang.Pair period) { - return QueryExtensions.inDatePeriod(this, period); - } - -} -]]> - - - - - - Non-annotated types - - - It is possible to create Querydsl query types for non annotated types by - creating @QueryEntities annotations. Just place a QueryEntities annotation into a - package of your choice and the classes to mirrored in the value attribute. - - - - To actually create the types use the com.querydsl.apt.QuerydslAnnotationProcessor. - In Maven you do it like this: - - - - - - ... - - com.mysema.maven - apt-maven-plugin - 1.1.3 - - - - process - - - target/generated-sources/java - com.querydsl.apt.QuerydslAnnotationProcessor - - - - - ... - - - -]]> - - - - - - Classpath based code generation - - For cases where annotated Java sources - are not available, such as the usage of a different JVM - language such as Scala or Groovy or annotation addition via bytecode manipulation the - GenericExporter - class can be used to scan the classpath for annotated classes and - generate query types for them. - - - To make GenericExporter available add a dependency to the querydsl-codegen - module to your project, or to be more precise - io.github.openfeign.querydsl:querydsl-codegen:${querydsl.version}. - - - Below is an example for JPA - - - - This will export all the JPA annotated classes in the package of the DomainClass - class and subpackages to the target/generated-sources/java directory. - - - - - Usage via Maven - - The goals generic-export, jpa-export and jdo-export of the querydsl-maven-plugin - can be used for GenericExporter usage via Maven. - - - - The different goals are mapped to the Querydsl, JPA and JDO annotations. - - - The configuration elements are - - - Maven configuration - - - - - - - Type - Element - Description - - - - - File - targetFolder - target folder for generated sources - - - boolean - scala - true, if Scala sources should be generated instead (default: false) - - - String[] - packages - packages to be introspected for entity classes - - - boolean - handleFields - true, if fields should be treated as properties (default: true) - - - boolean - handleMethods - true, if getters should be treated as properties (default: true) - - - String - sourceEncoding - charset encoding for the generated source files - - - boolean - testClasspath - true, if the test classpath should be used instead - - - -
- - Here is an example for JPA annotated classes - - - - - ... - - io.github.openfeign.querydsl - querydsl-maven-plugin - ${querydsl.version} - - - process-classes - - jpa-export - - - target/generated-sources/java - - com.example.domain - - - - - - ... - - - -]]> - - This will export the JPA annotated classes of the com.example.domain package and - subpackages to the target/generated-sources/java directory. - - - If you need to compile the generated sources directly after that, then you can use - the compile goal for that. - - - - - compile - - - target/generated-sources/scala - - -]]> - - The compile goal has the following configuration elements - - - - Maven configuration - - - - - - - Type - Element - Description - - - - - File - sourceFolder - source folder with generated sources - - - String - sourceEncoding - charset encoding of sources - - - String - source - -source option for the compiler - - - String - target - -target option for the compiler - - - boolean - testClasspath - true, if the test classpath should be used instead - - - Map - compilerOptions - options for the compiler - - - -
- - All options except sourceFolder are optional. - - -
- - - - Scala support - - If you need Scala output of the classes, use a variant of the following - configuration - - - - - - ... - - io.github.openfeign.querydsl - querydsl-maven-plugin - ${querydsl.version} - - - io.github.openfeign.querydsl - querydsl-scala - ${querydsl.version} - - - org.scala-lang - scala-library - ${scala.version} - - - - - - jpa-export - - - target/generated-sources/scala - true - - com.example.domain - - - - - - ... - - - -]]> - - - -
- - diff --git a/querydsl-docs/src/main/docbook/en-US/content/general/creating-queries.xml b/querydsl-docs/src/main/docbook/en-US/content/general/creating-queries.xml deleted file mode 100644 index e5fa188b1d..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/general/creating-queries.xml +++ /dev/null @@ -1,241 +0,0 @@ - - - Creating queries - - Query construction in Querydsl involves calling query methods with expression arguments. Since - query methods are mostly module specific and have already been presented in the tutorial section, - this part will focus on expressions. - - Expressions are normally constructed by accessing fields and calling methods on the generated - expression types of your domain module. For cases where code generation is not applicable generic ways - to construct expressions can be used instead. - - - Complex predicates - - - To construct complex boolean expressions, use the com.querydsl.core.BooleanBuilder class. It - implements Predicate and can be used in cascaded form: - - - getCustomer(String... names) { - QCustomer customer = QCustomer.customer; - JPAQuery query = queryFactory.selectFrom(customer); - BooleanBuilder builder = new BooleanBuilder(); - for (String name : names) { - builder.or(customer.name.eq(name)); - } - query.where(builder); // customer.name eq name1 OR customer.name eq name2 OR ... - return query.fetch(); -} -]]> - - BooleanBuilder is mutable and represents initially null and after each and - or or call the result of the operation. - - - - - - Dynamic expressions - - - The com.querydsl.core.types.dsl.Expressions - class is a static factory class for dynamic expression construction. - The factory methods are named by the returned type and are mostly self-documenting. - - - - In general the Expressions class should be used only in cases where fluent DSL forms - can't be used, such as dynamic paths, custom syntax or custom operations. - - - The following expression - - - - could be constructed like this if Q-types wouldn't be available - - person = Expressions.path(Person.class, "person"); -Path personFirstName = Expressions.path(String.class, person, "firstName"); -Constant constant = Expressions.constant("P"); -Expressions.predicate(Ops.STARTS_WITH, personFirstName, constant); -]]> - - Path instances represent variables and properties, Constants are constants, - Operations are operations and TemplateExpression instances can be used to express - expressions as String templates. - - - - - - - Dynamic paths - - In addition to the Expressions based expression creation Querydsl provides - also a more fluent API for dynamic path creation. - - - For dynamic path generation the com.querydsl.core.types.dsl.PathBuilder class can be used. It extends - EntityPathBase and can be used as an alternative to class generation and alias-usage - for path generation. - - - - Compared to the Expressions API PathBuilder doesn't provide direct support for unknown operations - or custom syntax, but the syntax is closer to the normal DSL. - - - String property: - - entityPath = new -PathBuilder(User.class, "entity"); -// fully generic access -entityPath.get("userName"); -// .. or with supplied type -entityPath.get("userName", String.class); -// .. and correct signature -entityPath.getString("userName").lower(); -]]> - - List property with component type: - - - - Using a component expression type: - - - - Map property with key and value type: - - - - Using a component expression type: - - - - For PathBuilder validation a PathBuilderValidator can be used. It can be injected in the constructor - and will be used transitively for the new PathBuilder - - customer = new PathBuilder(Customer.class, "customer", validator); -]]> - - PathBuilderValidator.FIELDS will verify field existence, PathBuilderValidator.PROPERTIES validates - Bean properties and JPAPathBuilderValidator validates using a JPA metamodel. - - - - - - - Case expressions - - To construct case-when-then-else expressions use the - CaseBuilder class like this: - - - cases = new CaseBuilder() - .when(customer.annualSpending.gt(10000)).then("Premier") - .when(customer.annualSpending.gt(5000)).then("Gold") - .when(customer.annualSpending.gt(2000)).then("Silver") - .otherwise("Bronze"); -// The cases expression can now be used in a projection or condition -]]> - - For case expressions with equals-operations use the following simpler form instead: - - - cases = customer.annualSpending - .when(10000).then("Premier") - .when(5000).then("Gold") - .when(2000).then("Silver") - .otherwise("Bronze"); -// The cases expression can now be used in a projection or condition -]]> - - Case expressions are not yet supported in JDOQL. - - - - - - Casting expressions - - - To avoid a generic signature in expression types the type hierarchies are - flattened. The result is that all generated query types are direct subclasses of - com.querydsl.core.types.dsl.EntityPathBase - or - com.querydsl.core.types.dsl.BeanPath - and cannot be directly cast to their logical supertypes. - - - - Instead of a direct Java cast, the supertype reference is accessible via the - _super field. A _super-field is available in all generated query types with a single - supertype: - - - { - // ... -} - -// from BankAccount extends Account -QBankAccount extends EntityPathBase { - - public final QAccount _super = new QAccount(this); - - // ... -} -]]> - - To cast from a supertype to a subtype you can use the - as-method of the - EntityPathBase class: - - - - - - - - - Select literals - - Literals can be selected by referring to them via Constant expressions. Here is a simple example - - - - Constant expressions are often used in subqueries. - - - - diff --git a/querydsl-docs/src/main/docbook/en-US/content/general/result-handling.xml b/querydsl-docs/src/main/docbook/en-US/content/general/result-handling.xml deleted file mode 100644 index 9b1ffc8b52..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/general/result-handling.xml +++ /dev/null @@ -1,192 +0,0 @@ - - - Result handling - - Querydsl provides two ways to customize results, FactoryExpressions for row based transformation - and ResultTransformer for aggregation. - - The com.querydsl.core.types.FactoryExpression interface is used for Bean creation, - constructor invocation and for the creation of more complex objects. The functionality of the - FactoryExpression implementations of Querydsl can be accessed via the - com.querydsl.core.types.Projections class. - - For the com.querydsl.core.ResultTransformer interface GroupBy is the - main implementation. - - - - Returning multiple columns - - Since Querydsl 3.0 the default type for multi-column results is com.querydsl.core.Tuple. - Tuple provides a typesafe Map like interface to access column data from a Tuple row object. - - result = query.select(employee.firstName, employee.lastName) - .from(employee).fetch(); -for (Tuple row : result) { - System.out.println("firstName " + row.get(employee.firstName)); - System.out.println("lastName " + row.get(employee.lastName)); -}} -]]> - - This example could also have been written via the QTuple expression class like this - - result = query.select(new QTuple(employee.firstName, employee.lastName)) - .from(employee).fetch(); -for (Tuple row : result) { - System.out.println("firstName " + row.get(employee.firstName)); - System.out.println("lastName " + row.get(employee.lastName)); -}} -]]> - - - - - - Bean population - - In cases where Beans need to be populated based on the results of the query, Bean projections - can be used like this - - dtos = query.select( - Projections.bean(UserDTO.class, user.firstName, user.lastName)).fetch(); -]]> - - When fields should be directly used instead of setters the following variant can be - used instead - - dtos = query.select( - Projections.fields(UserDTO.class, user.firstName, user.lastName)).fetch(); -]]> - - - - - Constructor usage - - Constructor based row transformation can be used like this - - dtos = query.select( - Projections.constructor(UserDTO.class, user.firstName, user.lastName)).fetch(); -]]> - - As an alternative to the generic Constructor expression usage constructors - can also be annotated with the QueryProjection annotation: - - - - - And then you can use it like this in the query - - dtos = query.select(new QCustomerDTO(customer.id, customer.name)) - .from(customer).fetch(); -]]> - - While the example is Hibernate specific, this feature is - available in all modules. - - - If the type with the QueryProjection annotation is not an annotated entity - type, you can use the constructor projection like in the example, but if the - annotated type would be an entity type, then the constructor projection would need to be - created via a call to the static create method of the query type: - - - - - dtos = query.select(QCustomer.create(customer.id, customer.name)) - .from(customer).fetch(); -]]> - - Alternatively, if code generation is not an option, you can - create a constructor projection like this: - - - dtos = query - .select(Projections.constructor(Customer.class, customer.id, customer.name)) - .from(customer).fetch(); -]]> - - - - - - Result aggregation - - - The - com.querydsl.core.group.GroupBy - class provides aggregation functionality which can be used to aggregate query results - in memory. Below are some usage examples. - - - - Aggregating parent child relations - - - > results = query.from(post, comment) - .where(comment.post.id.eq(post.id)) - .transform(groupBy(post.id).as(list(comment))); -]]> - - This will return a map of post ids to related comments. - - Multiple result columns - - results = query.from(post, comment) - .where(comment.post.id.eq(post.id)) - .transform(groupBy(post.id).as(post.name, set(comment.id))); -]]> - - This will return a map of post ids to Group instances with - access to post name - and comment ids. - - - Group is the GroupBy equivalent to the Tuple interface. - - - More examples can be found - here - . - - - - - diff --git a/querydsl-docs/src/main/docbook/en-US/content/intro.xml b/querydsl-docs/src/main/docbook/en-US/content/intro.xml deleted file mode 100644 index eb3af3d5b1..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/intro.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - Introduction - - - Background - - - Querydsl was born out of the need to maintain HQL queries in a typesafe way. - Incremental construction of HQL queries requires String concatenation and results - in hard to read code. Unsafe references to domain types and properties - via plain Strings were another issue with String based HQL construction. - - - - With a changing domain model type-safety brings huge benefits in software - development. Domain changes are directly reflected in queries and autocomplete in - query construction makes query construction faster and safer. - - - - HQL for Hibernate was the first target language for Querydsl, but nowadays it - supports JPA, JDO, JDBC, Lucene, Hibernate Search, MongoDB, Collections and RDFBean - as backends. - - - - If you are completely new to database access in Java,https://www.marcobehler.com/guides/a-guide-to-accessing-databases-in-java contains a good overview of the various parts, pieces and options and shows you where exactly QueryDSL fits in. - - - - - - - Principles - - - Type safety - is the core principle of Querydsl. Queries are constructed based on generated query - types that reflect the properties of your domain types. Also function/method - invocations are constructed in a fully type-safe manner. - - - - Consistency - is another important principle. The query paths and operations are the same - in all implementations and also the Query interfaces have a common base interface. - - - - To get an impression of the expressivity of the Querydsl query and expression types go to - the javadocs and explore com.querydsl.core.Query, com.querydsl.core.Fetchable - and com.querydsl.core.types.Expression. - - - - - diff --git a/querydsl-docs/src/main/docbook/en-US/content/preface.xml b/querydsl-docs/src/main/docbook/en-US/content/preface.xml deleted file mode 100644 index 593af57ff5..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/preface.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - Preface - - - Querydsl is a framework which enables the construction of statically - typed SQL-like queries. Instead of writing queries as inline strings or externalizing them - into XML files they can be constructed via a fluent API like Querydsl. - - - - The benefits of using a fluent API in comparison to simple strings are for example - - - - - code completion in IDE - - - almost none syntactically invalid queries allowed - - - domain types and properties can be referenced safely - - - adopts better to refactoring changes in domain types - - - - - - diff --git a/querydsl-docs/src/main/docbook/en-US/content/troubleshooting.xml b/querydsl-docs/src/main/docbook/en-US/content/troubleshooting.xml deleted file mode 100644 index 22d719db9d..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/troubleshooting.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - Troubleshooting - - - Insufficient type arguments - - - Querydsl needs properly encoded List Set, Collection and Map properties in all code generation - scenarios. - - - When using improperly encoded fields or getters you might the following - stacktrace: - - (APTTypeModel.java:55) - at com.querydsl.apt.APTTypeModel.get(APTTypeModel.java:48) - at com.querydsl.apt.Processor$2.visitType(Processor.java:114) - ... 35 more -]]> - - - Examples of problematic field declarations and their corrections: - - - names; // RIGHT - - private Map employeesByName; // WRONG - - private Map employeesByName; // RIGHT -]]> - - - - - - - Multithreaded initialization of Querydsl Q-types - - When Querydsl Q-types are initialized from multiple threads, deadlocks can - occur, if the Q-types have circular dependencies. - - An easy to use solution is to initialize the classes in a single thread before - they are used in different threads. - - The com.querydsl.codegen.ClassPathUtils class can be used for that like this: - - - - Replace packageToLoad with the package of the classes you want to initialize. - - - - - - diff --git a/querydsl-docs/src/main/docbook/en-US/content/tutorials.xml b/querydsl-docs/src/main/docbook/en-US/content/tutorials.xml deleted file mode 100644 index 13b7bfbd2e..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/tutorials.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - Tutorials - - - Instead of a general Getting started guide we provide integration - guides for the main backends of Querydsl. - - - - - - - - - - - - - - \ No newline at end of file diff --git a/querydsl-docs/src/main/docbook/en-US/content/tutorials/collections.xml b/querydsl-docs/src/main/docbook/en-US/content/tutorials/collections.xml deleted file mode 100644 index 3eb4bb08a1..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/tutorials/collections.xml +++ /dev/null @@ -1,276 +0,0 @@ - - - - - Querying Collections - - The querydsl-collections module can be used with generated query types and - without. - The first section describes the usage without generated query types: - - - - Usage without generated query types - - - To use querydsl-collections without generated query types you need to - use the - Querydsl alias feature. Here are some examples. - - - - To get started, add the following static imports: - - - - - - And now create an alias instance for the Cat class. Alias instances can only be - created for non-final classes with an empty constructor. Make sure your class has one. - - - - The alias instance of type Cat and its getter invocations are - transformed into paths by wrapping them into dollar method invocations. - The call - c.getKittens() - for example is internally - transformed into the property path c.kittens inside the - dollar method. - - - - - - The following example is a variation of the previous, where the access - to the - list size happens inside the dollar-method invocation. - - - - - - All non-primitive and non-final typed properties of aliases are aliases - themselves. So you may cascade method calls until you hit a - primitive or non-final type (e.g. java.lang.String) in the dollar-method scope. - - - - e.g. - - - - - - is transformed into - c.mate.name - internally, but - - - - - - is not transformed properly, since the toLowerCase() invocation is not tracked. - - - Note also that you may only invoke getters, size(), contains(Object) and - get(int) on alias types. All other invocations throw exceptions. - - - - - - - Usage with generated query types - - - The example above can be expressed like this with generated expression types - - - - - When you use generated query types, you instantiate expressions instead of alias - instances - and use the property paths directly without any dollar-method wrapping. - - - - - - - Maven integration - - - Add the following dependencies to your Maven project: - - - - io.github.openfeign.querydsl - querydsl-apt - ${querydsl.version} - provided - - - - io.github.openfeign.querydsl - querydsl-collections - ${querydsl.version} - -]]> - - - - If you are not using JPA or JDO you can generate expression types for your - domain types by - annotating them with the - com.querydsl.core.annotations.QueryEntity - annotation and adding the - following plugin configuration into your Maven configuration (pom.xml): - - - - - - ... - - com.mysema.maven - apt-maven-plugin - 1.1.3 - - - - process - - - target/generated-sources/java - com.querydsl.apt.QuerydslAnnotationProcessor - - - - - ... - - - -]]> - - - - - - Ant integration - - Place the jar files from the full-deps bundle on your classpath and use the - following tasks for Querydsl code generation: - - - - - - - - - - - - - - - - -]]> - - - Replace - src - with your main source folder, - generated - with your folder for generated sources and - build - with your target folder. - - - - - - - Hamcrest matchers - - Querydsl Collections provides Hamcrest matchers. With these imports - - - - they can be used like this: - - - - - The Hamcrest matchers have been contributed by - Jeroen van Schagen - . - - - - - - - Usage with the Eclipse Compiler for Java - - If Querydsl Collections is used with a JRE where the system compiler is not available, - CollQuery instances can also be configured to use the Eclipse Compiler for Java (ECJ) instead: - - - - - - \ No newline at end of file diff --git a/querydsl-docs/src/main/docbook/en-US/content/tutorials/hibernate-search.xml b/querydsl-docs/src/main/docbook/en-US/content/tutorials/hibernate-search.xml deleted file mode 100644 index 9e2cb18a89..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/tutorials/hibernate-search.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - Querying Hibernate Search - - This chapter describes the querying functionality of - the Hibernate Search module. - - - - - Creating the Querydsl query types - - See Querying JPA/Hibernate sources - for instructions on how to create query types. - - - - - Querying - - Querying with Querydsl Hibernate Search is as simple as this: - - - query = new SearchQuery(session, user); -List list = query - .where(user.firstName.eq("Bob")) - .fetch(); -]]> - - - - - General usage - - - For general usage instructions see - Querying Lucene sources - . - - - - In the query serialization the only difference to the Querydsl Lucene module is that - paths are treated differently. - For org.hibernate.search.annotations.Field - annotated properties the - name attribute is used with the property name as fallback for the field name. - - - - diff --git a/querydsl-docs/src/main/docbook/en-US/content/tutorials/jdo.xml b/querydsl-docs/src/main/docbook/en-US/content/tutorials/jdo.xml deleted file mode 100644 index 031a155384..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/tutorials/jdo.xml +++ /dev/null @@ -1,526 +0,0 @@ - - - - Querying JDO - - - Querydsl defines a general statically typed syntax for querying on top of - persisted domain model data. JDO and JPA are the primary integration - technologies for - Querydsl. This guide describes how to use Querydsl - in combination with JDO. - - - - Maven integration - - - Add the following dependencies to your Maven project: - - - - io.github.openfeign.querydsl - querydsl-apt - ${querydsl.version} - provided - - - - io.github.openfeign.querydsl - querydsl-jdo - ${querydsl.version} - -]]> - - - And now, configure the Maven APT plugin which generates the query types - used by - Querydsl: - - - - - - ... - - com.mysema.maven - apt-maven-plugin - 1.1.3 - - - - process - - - target/generated-sources/java - com.querydsl.apt.jdo.JDOAnnotationProcessor - - - - - ... - - - -]]> - - - The JDOAnnotationProcessor finds domain types annotated with the - javax.jdo.annotations.PersistenceCapable annotation and generates - query types for them. - - - - Run clean install and you will get your query types generated into - target/generated-sources/java. - - - - If you use Eclipse, run mvn eclipse:eclipse to update your Eclipse project to - include target/generated-sources/java as a source folder. - - - - Now you are able to construct JDO query instances and instances of the query domain model. - - - - - - - Ant integration - - Place the jar files from the full-deps bundle on your classpath and use the - following tasks for Querydsl code generation: - - - - - - - - - - - - - - - - -]]> - - - Replace - src - with your main source folder, - generated - with your folder for generated sources - and - build - with your target folder. - - - - - - - Using query types - - - To create queries with Querydsl you need to instantiate variables and Query - implementations. We will start with the variables. - - - - Let's assume that your project has the following domain type: - - - - - - Querydsl will generate a query type with the simple name QCustomer into the - same package as Customer. QCustomer can be used as a statically - typed variable in Querydsl as a representative for the - Customer type. - - - - QCustomer has a default instance variable which can be accessed as a static - field: - - - - - - Alternatively you can define your own Customer variables like this: - - - - - - QCustomer reflects all the properties of the original type Customer as public - fields. The firstName field can be accessed like this - - - - - - - - - Querying with JDO - - - For the JDO-module JDOQuery is the main Query implementation. It - is instantiated like this: - - - query = new JDOQuery(pm); -]]> - - For the examples of this chapter the queries are created via a JDOQueryFactory instance. - JDOQueryFactory should be the preferred option to obtain JDOQuery instances. - - - To retrieve the customer with the first name Bob you would construct a - query like this: - - - - - - The selectFrom call defines the query source and projection, the where part defines the - filter and fetchOne tells Querydsl to return a single element. Easy, right? - - - Alternatively you can express it also like this - - - - - To create a query with multiple sources you just use the JDOQuery class like this: - - - - - - And to use multiple filters use it like this - - - - - Or like this - - - - If you want to combine the filters via "or" then use the following pattern - - - - - - - - - General usage - - Use the the cascading methods of the JDOQuery class like this - - - select: - Set the projection of the query. (Not necessary if created via query factory) - - - - from: - Add query sources here, the first argument becomes the main source - and the others are treated as variables. - - - - where: - Add query filters, either in varargs form separated via commas or - cascaded via the and-operator. - - - - groupBy: - Add group by arguments in varargs form. - - - - having: - Add having filters of the "group by" grouping as an varargs array of - Predicate expressions. - - - - orderBy: - Add ordering of the result as an varargs array of order expressions. - Use asc() and desc() on numeric, string and other comparable expression to access the - OrderSpecifier instances. - - - - limit, offset, restrict: - Set the paging of the result. Limit for max results, - offset for skipping rows and restrict for defining both in one call. - - - - - - - Ordering - - The syntax for declaring ordering is - - - - - - - - Grouping - - Grouping can be done in the following form - - - - - - - - Delete clauses - - Delete clauses in Querydsl JDO follow a simple delete-where-execute form. Here - are some examples: - - - - - The second parameter of the JDODeleteClause constructor is the entity to be - deleted. The where call is optional and the execute call performs the deletion and - returns the amount of deleted entities. - - - - - - - Subqueries - - To create a subquery you can use one of the factory methods of JDOExpressions - and add the query parameters via from, where etc. - - - - - represents the following native JDO query - - -SELECT this FROM com.querydsl.jdo.models.company.Department -WHERE this.size == -(SELECT max(d.size) FROM com.querydsl.jdo.models.company.Department d) - - - Another example - - - - which represents the following native JDO query - - -SELECT this FROM com.querydsl.jdo.models.company.Employee -WHERE this.weeklyhours > -(SELECT avg(e.weeklyhours) FROM this.department.employees e WHERE e.manager == this.manager) - - - - - - - Using Native SQL - - Querydsl supports Native SQL in JDO via the JDOSQLQuery class. - - To use it, you must generate Querydsl query types for your SQL schema. This can - be done for example with the following Maven configuration: - - - - - - ... - - io.github.openfeign.querydsl - querydsl-maven-plugin - ${querydsl.version} - - - - export - - - - - org.apache.derby.jdbc.EmbeddedDriver - jdbc:derby:target/demoDB;create=true - com.mycompany.mydomain - ${project.basedir}/target/generated-sources/java - - - - org.apache.derby - derby - ${derby.version} - - - - ... - - - -]]> - - When the query types have successfully been generated into the location of your - choice, you can use them in your queries. - - - Single column query: - - query = new JDOSQLQuery(pm, templates); -List names = query.select(cat.name).from(cat).fetch(); -]]> - - Query multiple columns: - - (pm, templates); -List rows = query.select(cat.id, cat.name).from(cat).fetch(); -]]> - - Query all columns: - - rows = query.select(cat.all()).from(cat).fetch(); - ]]> - - Query with joins: - - (pm, templates); -cats = query.select(catEntity).from(cat) - .innerJoin(mate).on(cat.mateId.eq(mate.id)) - .where(cat.dtype.eq("Cat"), mate.dtype.eq("Cat")) - .fetch(); -]]> - - Query and project into DTO: - - (pm, templates); -List catDTOs = query.select(Projections.constructor(CatDTO.class, cat.id, cat.name)) - .from(cat) - .orderBy(cat.name.asc()) - .fetch(); -]]> - - - - \ No newline at end of file diff --git a/querydsl-docs/src/main/docbook/en-US/content/tutorials/jpa.xml b/querydsl-docs/src/main/docbook/en-US/content/tutorials/jpa.xml deleted file mode 100644 index 7b6afadc00..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/tutorials/jpa.xml +++ /dev/null @@ -1,723 +0,0 @@ - - - - - Querying JPA - - - Querydsl defines a general statically typed syntax for querying on top of - persisted domain model data. JDO and JPA are the primary integration - technologies for Querydsl. This guide describes how to use Querydsl - in combination with JPA. - - - - Querydsl for JPA is an alternative to both JPQL and Criteria queries. It combines the - dynamic nature of Criteria queries with the expressiveness of JPQL and all that in a fully - typesafe manner. - - - - Maven integration - - - Add the following dependencies to your Maven project: - - - - io.github.openfeign.querydsl - querydsl-apt - ${querydsl.version} - provided - - - - io.github.openfeign.querydsl - querydsl-jpa - ${querydsl.version} - -]]> - - - And now, configure the Maven APT plugin: - - - - - - ... - - com.mysema.maven - apt-maven-plugin - 1.1.3 - - - - process - - - target/generated-sources/java - com.querydsl.apt.jpa.JPAAnnotationProcessor - - - - - ... - - - -]]> - - - The JPAAnnotationProcessor finds domain types annotated with the - jakarta.persistence.Entity annotation and generates query types for them. - - - - If you use Hibernate annotations in your domain types you should use - the APT processor - com.querydsl.apt.hibernate.HibernateAnnotationProcessor - instead. - - - - Run clean install and you will get your Query types generated into - target/generated-sources/java. - - - - If you use Eclipse, run mvn eclipse:eclipse to update your Eclipse project to - include target/generated-sources/java as a source folder. - - - - Now you are able to construct JPA query instances and instances of - the query domain model. - - - - - - - Ant integration - - Place the jar files from the full-deps bundle on your classpath and use the - following tasks for Querydsl code generation: - - - - - - - - - - - - - - - - -]]> - - - Replace - src - with your main source folder, - generated - with your folder for generated sources - and - build - with your target folder. - - - - - - - Using Querydsl JPA in Roo - - - If you are using Querydsl JPA with Spring Roo you can replace - com.querydsl.apt.jpa.JPAAnnotationProcessor - with - com.querydsl.apt.roo.RooAnnotationProcessor - which will handle - @RooJpaEntity - and - @RooJpaActiveRecord - annotated classes instead of - @Entity - annotated classes. - - - - APT based code generation doesn't work well with AspectJ IDTs. - - - - - - - Generating the model from hbm.xml files - - If you are using Hibernate with an XML based configuration, you can use the XML - metadata to create your Querydsl model. - - - - com.querydsl.jpa.codegen.HibernateDomainExporter - provides the - functionality for this: - - - - - The HibernateDomainExporter needs to be executed within a classpath where the - domain types are visible, since the property types are resolved - via reflection. - - - All JPA annotations are ignored, but Querydsl annotations such as @QueryInit and - @QueryType are taken into account. - - - - - - - Using query types - - - To create queries with Querydsl you need to instantiate variables and - Query implementations. We will start with the variables. - - - - Let's assume that your project has the following domain type: - - - - - - Querydsl will generate a query type with the simple name QCustomer into the - same package as Customer. QCustomer can be used as a statically - typed variable in Querydsl queries as a representative for the - Customer type. - - - - QCustomer has a default instance variable which can be accessed as a static - field: - - - - - - Alternatively you can define your own Customer variables like this: - - - - - - - - - Querying - - The Querydsl JPA module supports both the JPA and the Hibernate API. - - - To use the JPA API you use JPAQuery instances for your queries like - this: - - - query = new JPAQuery(entityManager); -]]> - - If you are using the Hibernate API instead, you can instantiate a - HibernateQuery - like this: - - - query = new HibernateQuery(session); -]]> - - Both JPAQuery and HibernateQuery implement the JPQLQuery interface. - - - For the examples of this chapter the queries are created via a JPAQueryFactory instance. - JPAQueryFactory - should be the preferred option to obtain JPAQuery instances. - - - For the Hibernate API HibernateQueryFactory can be used - - - - To retrieve the customer with the first name Bob you would construct a - query like this: - - - - - - The selectFrom call defines the query source and projection, the where part defines the - filter and fetchOne tells Querydsl to return a single element. Easy, right? - - - - To create a query with multiple sources you use the query like this: - - - - - - And to use multiple filters use it like this - - - - - Or like this - - - - In native JPQL form the query would be written like this: - - - select customer from Customer as customer - where customer.firstName = "Bob" and customer.lastName = "Wilson" - - - If you want to combine the filters via "or" then use the following pattern - - - - - - - - - Using joins - - Querydsl supports the following join variants in JPQL: inner join, join, left - join and right join. Join usage is typesafe, and follows the following pattern: - - - - - The native JPQL version of the query would be - - - select cat from Cat as cat - inner join cat.mate as mate - left outer join cat.kittens as kitten - - - Another example - - - - With the following JPQL version - - - select cat from Cat as cat - left join cat.kittens as kitten - on kitten.bodyWeight > 10.0 - - - - - - - General usage - - Use the the cascading methods of the JPQLQuery interface like this - - - select: - Set the projection of the query. (Not necessary if created via query factory) - - - - from: - Add the query sources here. - - - - innerJoin, join, leftJoin, rightJoin, on: - Add join elements using these constructs. - For the join methods the first argument is the join source and the second the target - (alias). - - - - where: - Add query filters, either in varargs form separated via commas or - cascaded via the and-operator. - - - - groupBy: - Add group by arguments in varargs form. - - - - having: - Add having filters of the "group by" grouping as an varags array of - Predicate expressions. - - - - orderBy: - Add ordering of the result as an varargs array of order expressions. - Use asc() and desc() on numeric, string and other comparable expression to access the - OrderSpecifier instances. - - - - limit, offset, restrict: - Set the paging of the result. Limit for max results, - offset for skipping rows and restrict for defining both in one call. - - - - - - - Ordering - - The syntax for declaring ordering is - - - - which is equivalent to the following native JPQL - - - select customer from Customer as customer - order by customer.lastName asc, customer.firstName desc - - - - - - - Grouping - - Grouping can be done in the following form - - - - which is equivalent to the following native JPQL - - - select customer.lastName - from Customer as customer - group by customer.lastName - - - - - - - Delete clauses - Delete clauses in Querydsl JPA follow a simple delete-where-execute form. Here - are some - examples: - - - - - The where call is optional and the execute call performs the deletion and returns the - amount of deleted entities. - - - DML clauses in JPA don't take JPA level cascade rules into account and don't provide - fine-grained second level cache interaction. - - - - - Update clauses - - Update clauses in Querydsl JPA follow a simple update-set/where-execute form. - Here are some examples: - - - - - The set invocations define the property updates in SQL-Update-style and the execute call - performs the Update and returns the amount of updated entities. - - - DML clauses in JPA don't take JPA level cascade rules into account and don't provide - fine-grained second level cache interaction. - - - - - - - Subqueries - - To create a subquery you use the static factory methods of JPAExpressions and - define the query parameters via from, where etc. - - - - - Another example - - - - - - - Exposing the original query - - If you need to tune the original Query before the execution of the query you - can expose it like this: - - - - - - - - Using Native SQL in JPA queries - - Querydsl supports Native SQL in JPA via the JPASQLQuery class. - - - To use it, you must generate Querydsl query types for your SQL schema. This can - be done for example with the following Maven configuration: - - - - - - ... - - io.github.openfeign.querydsl - querydsl-maven-plugin - ${querydsl.version} - - - - export - - - - - org.apache.derby.jdbc.EmbeddedDriver - jdbc:derby:target/demoDB;create=true - com.mycompany.mydomain - ${project.basedir}/target/generated-sources/java - - - - org.apache.derby - derby - ${derby.version} - - - - ... - - - -]]> - - When the query types have successfully been generated into the location of your - choice, you can use them in your queries. - - - Single column query: - - query = new JPASQLQuery(entityManager, templates); -List names = query.select(cat.name).from(cat).fetch(); -]]> - - If you mix entity (e.g. QCat) and table (e.g. SAnimal) references in your query you need to make sure that - they - use the same variable names. SAnimal.animal has the variable name "animal", so a new instance - (new SAnimal("cat")) was used instead. - - - An alternative pattern could be - - - - Query multiple columns: - - (entityManager, templates); -List rows = query.select(cat.id, cat.name).from(cat).fetch(); -]]> - - Query all columns: - - rows = query.select(cat.all()).from(cat).fetch(); - ]]> - - Query in SQL, but project as entity: - - (entityManager, templates); -List cats = query.select(catEntity).from(cat).orderBy(cat.name.asc()).fetch(); -]]> - - Query with joins: - - (entityManager, templates); -cats = query.select(catEntity).from(cat) - .innerJoin(mate).on(cat.mateId.eq(mate.id)) - .where(cat.dtype.eq("Cat"), mate.dtype.eq("Cat")) - .fetch(); -]]> - - Query and project into DTO: - - (entityManager, templates); -List catDTOs = query.select(Projections.constructor(CatDTO.class, cat.id, cat.name)) - .from(cat) - .orderBy(cat.name.asc()) - .fetch(); -]]> - - If you are using the Hibernate API instead of the JPA API, then use - HibernateSQLQuery - instead. - - - - - diff --git a/querydsl-docs/src/main/docbook/en-US/content/tutorials/lucene.xml b/querydsl-docs/src/main/docbook/en-US/content/tutorials/lucene.xml deleted file mode 100644 index 983796a6c9..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/tutorials/lucene.xml +++ /dev/null @@ -1,242 +0,0 @@ - - - - - Querying Lucene - - This chapter describes the querying functionality of the Lucene module. - - - Maven integration - - - Querydsl Lucene can be used via the querydsl-lucene3 module for Lucene 3, querydsl-lucene4 - for Lucene 4 and querydsl-lucene5 for Lucene 5 - - - Lucene 3: - - - io.github.openfeign.querydsl - querydsl-lucene3 - ${querydsl.version} - -]]> - - Lucene 4: - - - io.github.openfeign.querydsl - querydsl-lucene4 - ${querydsl.version} - -]]> - - - Lucene 5: - - - io.github.openfeign.querydsl - querydsl-lucene5 - ${querydsl.version} - -]]> - - - - - Creating the query types - - With fields year and title a manually created query type could look something - like this: - - { - private static final long serialVersionUID = -4872833626508344081L; - - public QDocument(String var) { - super(Document.class, PathMetadataFactory.forVariable(var)); - } - - public final StringPath year = createString("year"); - - public final StringPath title = createString("title"); -} -]]> - - QDocument represents a Lucene document with the fields year and title. - - Code generation is not available for Lucene, since no schema data is available. - - - - - - Querying - - Querying with Querydsl Lucene is as simple as this: - - documents = query - .where(doc.year.between("1800", "2000").and(doc.title.startsWith("Huckle")) - .fetch(); -]]> - - which is transformed into the following Lucene query: - - - - - - - - General usage - - Use the the cascading methods of the LuceneQuery class like this - - - where: - Add the query filters, either in varargs form separated via commas or - cascaded via the and-operator. Supported operations are operations performed on PStrings except - - matches - - , - indexOf - , - charAt - . Currently - in - is - not supported, but will be in the future. - - - - orderBy: - Add ordering of the result as an varargs array of order expressions. - Use asc() and desc() on numeric, string and other comparable expression to access the - OrderSpecifier instances. - - - - limit, offset, restrict: - Set the paging of the result. Limit for max results, - offset for skipping rows and restrict for defining both in one call. - - - - - - - Ordering - - The syntax for declaring ordering is - - - - which is equivalent to the following Lucene query - - -title:* - - - The results are sorted ascending based on title and year. - - Alternatively a sort method call can be used to declare the sort logic as a Sort - instance instead - - - - - - - - Limit - - The syntax for declaring a limit is - - - - - - - Offset - - The syntax for declaring an offset is - - - - - - - - Fuzzy searches - - Fuzzy searches can be expressed via fuzzyLike methods in the - com.querydsl.lucene3.LuceneExpressions class: - - - - - - - - - Applying Lucene filters to queries - - It is possible to apply a single Lucene filter to the query like this: - - - - A shortcut for distinct filtering is provided via the distinct(Path) method: - - - - - - - diff --git a/querydsl-docs/src/main/docbook/en-US/content/tutorials/mongodb.xml b/querydsl-docs/src/main/docbook/en-US/content/tutorials/mongodb.xml deleted file mode 100644 index ad9f26a142..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/tutorials/mongodb.xml +++ /dev/null @@ -1,223 +0,0 @@ - - - - - Querying Mongodb - - This chapter describes the querying functionality of the Mongodb module. - - - Maven integration - - - Add the following dependencies to your Maven project: - - - - io.github.openfeign.querydsl - querydsl-apt - ${querydsl.version} - provided - - - - io.github.openfeign.querydsl - querydsl-mongodb - ${querydsl.version} - -]]> - - - And now, configure the Maven APT plugin which generates the query types - used by Querydsl: - - - - - - ... - - com.mysema.maven - apt-maven-plugin - 1.1.3 - - - - process - - - target/generated-sources/java - com.querydsl.apt.morphia.MorphiaAnnotationProcessor - - - - - ... - - - -]]> - - - The MorphiaAnnotationProcessor finds domain types annotated with the - com.google.code.morphia.annotations.Entity - annotation and generates Querydsl query types for them. - - - - Run clean install and you will get your Query types generated into - target/generated-sources/java. - - - - If you use Eclipse, run mvn eclipse:eclipse to update your Eclipse project to - include target/generated-sources/java as a source folder. - - - - Now you are able to construct Mongodb queries and instances of the - query domain model. - - - - - - - Querying - - Querying with Querydsl Mongodb with Morphia is as simple as this: - - - query = new MorphiaQuery(morphia, datastore, user); -List list = query - .where(user.firstName.eq("Bob")) - .fetch(); -]]> - - - - - - General usage - - Use the the cascading methods of the MongodbQuery class like this - - - where: - Add the query filters, either in varargs form separated via commas or - cascaded via the and-operator. Supported operations are operations performed on PStrings except - - matches - - , - indexOf - , - charAt - . Currently - in - is - not supported, but will be in the future. - - - - orderBy: - Add ordering of the result as an varargs array of order expressions. - Use asc() and desc() on numeric, string and other comparable expression to access the - OrderSpecifier instances. - - - - limit, offset, restrict: - Set the paging of the result. Limit for max results, - offset for skipping rows and restrict for defining both in one call. - - - - - - - Ordering - - The syntax for declaring ordering is - - - - The results are sorted ascending based on title and year. - - - - - Limit - - The syntax for declaring a limit is - - - - - - - Offset - - The syntax for declaring an offset is - - - - - - - - Geospatial queries - - Support for geospatial queries is available for Double typed arrays (Double[]) - via the near-method: - - - - - - - - - Select only relevant fields - - To select only relevant fields you can use the overloaded projection methods - fetch, iterate, fetchOne and fetchFirst methods like this - - - - - This query will load only the title and path fields of the documents. - - - - diff --git a/querydsl-docs/src/main/docbook/en-US/content/tutorials/scala.xml b/querydsl-docs/src/main/docbook/en-US/content/tutorials/scala.xml deleted file mode 100644 index 8ff893bb15..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/tutorials/scala.xml +++ /dev/null @@ -1,256 +0,0 @@ - - - - - Querying in Scala - - Generic support for Querydsl usage in Scala is available via querydsl-scala - module. To add it to your Maven build, use the following snippet: - - - - io.github.openfeign.querydsl - querydsl-scala - ${querydsl.version} - -]]> - - - - DSL expressions for Scala - - Querydsl for Scala provides an alternative DSL for expression construction. The - Scala DSL utilizes language features such as operator overloading, - function pointers and implicit imports for enhanced readability and conciseness. - - - Here is an overview of the main alternatives : - - - - 5 -expr goe 5 expr >= 5 -expr notBetween(2,6) expr not between (2,6) -expr negate -expr - -// numeric -expr add 3 expr + 3 -expr subtract 3 expr - 3 -expr divide 3 expr / 3 -expr multiply 3 expr * 3 -expr mod 5 expr % 5 - -// collection -list.get(0) list(0) -map.get("X") map("X") -]]> - - - - - - Querying with SQL - - - Like with Querydsl SQL for Java you need to generate Query types to be able to construct - your queries. The following code examples show how this is done: - - - Generation without Bean types : - - - - Generation with Bean types : - - - - - - - Code generation - - Scala sources for SQL metatypes and projections can be generated with - querydsl-maven-plugin. Here is an example configuration - - - - - - ... - - io.github.openfeign.querydsl - querydsl-maven-plugin - ${querydsl.version} - - com.mysql.jdbc.Driver - jdbc:mysql://localhost:3306/test - matko - matko - com.example.schema - ${project.basedir}/src/main/scala - true - true - - - - mysql - mysql-connector-java - 5.1.16 - - - io.github.openfeign.querydsl - querydsl-scala - ${querydsl.version} - - - org.scala-lang - scala-library - ${scala.version} - - - - ... - - - -]]> - - The maven goal to execute is querydsl:export. - - - - - - - Querying with other backends - - When querying with other backends the Expression model has to be created - manually or alternatively the alias functionality can be used. - - - Here is a minimal example with JPA : - - - - And here are some query examples - - List - - - - Unique result - - - - Long where - - - - Order - - - - Not null - - - - The factory method for query creation is - - - - In addition to queries you need variables which can be created like this - - - - Note: the Scala support is not yet available if you use Hibernate with an XML based configuration. HibernateDomainExporter currently only outputs Java source files. - - - - diff --git a/querydsl-docs/src/main/docbook/en-US/content/tutorials/spatial.xml b/querydsl-docs/src/main/docbook/en-US/content/tutorials/spatial.xml deleted file mode 100644 index f5dfec6097..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/tutorials/spatial.xml +++ /dev/null @@ -1,186 +0,0 @@ - - - - - Querydsl Spatial - - Support for Spatial queries is available via the Querydsl Spatial module, which is an extension - module to the SQL module. The Spatial module supports the object model of Simple Feature Access in queries - and object binding. - - The geolatte project is used for the object model. - - - - - Maven integration - - - Add the following dependency to your Maven project: - - - - io.github.openfeign.querydsl - querydsl-sql-spatial - ${querydsl.version} - -]]> - - Additionally the following database specific extra dependencies: - - - - org.postgis - postgis-jdbc - 1.3.3 - provided - - - - - oracle - sdoapi - 11.2.0 - provided - -]]> - - - - - - Code generation via Maven - - The code generation for Querydsl SQL can be set to detect the usage of spatial types in - database schemas and use geolatte types in these case via the spatial property: - - - - - ... - - io.github.openfeign.querydsl - querydsl-maven-plugin - ${querydsl.version} - ... - - ... - true - - - ... - - - -]]> - - - - - - Runtime configuration - - The runtime configuration aspect of the spatial module is that instead of the normal - SQLTemplates instances, spatial enabled instances are used. Below is a list of spatial enabled - SQLTemplates classes. - - - - GeoDBTemplates (for H2) - - - MySQLSpatialTemplates - - - OracleSpatialTemplates (alpha stage) - - - PostGISTemplates - - - SQLServer2008SpatialTemplates - - - TeradataSpatialTemplates - - - - - - - - Querying - - With code generation and runtime configuration set for spatial types we can now try - queries with it. - - - - Filter by Distance - - - - In addition to straight distance between geometries spherical and spheroidal distance are provided via - distanceSphere and distanceSpheroid. - - - - - - Contains - - - - - - - - Intersection - - - - - - - - Access to the SPATIAL_REF_SYS table - - Unified access to the SPATIAL_REF_SYS standard table is provided via the QSpatialRefSys - and SpatialRefSys classes. SPATIAL_REF_SYS contains data about the supported spatial reference systems. - - referenceSystems = query.select(spatialRefSys).from(spatialRefSys).fetch(); -]]> - - - - - - - - Inheritance - - In case you use only generic geometry types in your database schema you can use conversion methods - in the object model to convert to more specific types. - - geometry = shapes.geometry; -PointPath point = geometry.asPoint(); -NumberExpression pointX = point.x(); // x() is not available on GeometryExpression/GeometryPath -]]> - - - - diff --git a/querydsl-docs/src/main/docbook/en-US/content/tutorials/sql.xml b/querydsl-docs/src/main/docbook/en-US/content/tutorials/sql.xml deleted file mode 100644 index bc78e8eba0..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/content/tutorials/sql.xml +++ /dev/null @@ -1,1287 +0,0 @@ - - - - - Querying SQL - - This chapter describes the query type generation and querying functionality of the - SQL module. - - - Maven integration - - - Add the following dependencies to your Maven project: - - - - io.github.openfeign.querydsl - querydsl-sql - ${querydsl.version} - - - - io.github.openfeign.querydsl - querydsl-sql-codegen - ${querydsl.version} - provided - -]]> - - The querydsl-sql-codegen dependency can be skipped, if code generation happens - via Maven. - - - - - - Code generation via Maven - - This functionality should be primarily used via the Maven plugin. Here is an example: - - - - - - ... - - io.github.openfeign.querydsl - querydsl-maven-plugin - ${querydsl.version} - - - - export - - - - - org.apache.derby.jdbc.EmbeddedDriver - jdbc:derby:target/demoDB;create=true - com.myproject.domain - ${project.basedir}/target/generated-sources/java - - - - org.apache.derby - derby - ${derby.version} - - - - ... - - - -]]> - - - Use the goal test-export - to treat the target folder as a test source folder for use with test code. - - - - Parameters - - - - - - Name - Description - - - - - jdbcDriver - class name of the JDBC driver - - - jdbcUrl - JDBC url - - - jdbcUser - JDBC user - - - jdbcPassword - JDBC password - - - namePrefix - name prefix for generated query classes (default: Q) - - - nameSuffix - name suffix for generated query classes (default: ) - - - beanPrefix - name prefix for generated bean classes - - - beanSuffix - name suffix for generated bean classes - - - packageName - package name where source files should be generated - - - beanPackageName - package name where bean files should be generated, (default: - packageName) - - - beanInterfaces - array of interface classnames to add to the bean classes (default: empty) - - - beanAddToString - set to true to create a default toString() implementation (default: false) - - - beanAddFullConstructor - set to true to create a full constructor in addition to public empty (default: false) - - - beanPrintSupertype - set to true to print the supertype as well (default: false) - - - schemaPattern - a schema name pattern in LIKE pattern form; must match the schema name as it is stored in the database, - multiple can be separated by comma - (default: null) - - - tableNamePattern - a table name pattern in LIKE pattern form; must match the table name as it is stored in the database, - multiple can be separated by comma - (default: null) - - - targetFolder - target folder where sources should be generated - - - beansTargetFolder - target folder where bean sources should be generated, defaults to the same value as targetFolder - - - namingStrategyClass - class name of the NamingStrategy class (default: DefaultNamingStrategy) - - - - beanSerializerClass - class name of the BeanSerializer class (default: BeanSerializer) - - - serializerClass - class name of the Serializer class (default: MetaDataSerializer) - - - exportBeans - set to true to generate beans as well, see section 2.14.13 (default: - false) - - - innerClassesForKeys - set to true to generate inner classes for keys (default: false) - - - validationAnnotations - set to true to enable serialization of validation annotations - (default: false) - - - columnAnnotations - export column annotations (default: false) - - - createScalaSources - whether to export Scala sources instead of Java sources, (default: - false) - - - schemaToPackage - append schema name to package (default: false) - - - lowerCase - lower case transformation of names (default: false) - - - exportTables - export tables (default: true) - - - exportViews - export views (default: true) - - - exportPrimaryKeys - export primary keys (default: true) - - - tableTypesToExport - Comma-separated list of table types to export (allowable values will depend on JDBC driver). Allows for arbitrary set of types to be exported, e.g.: "TABLE, MATERIALIZED VIEW". The exportTables and exportViews parameters will be ignored if this parameter is set. (default: none) - - - exportForeignKeys - export foreign keys (default: true) - - - exportDirectForeignKeys - export direct foreign keys (default: true) - - - exportInverseForeignKeys - export inverse foreign keys (default: true) - - - customTypes - Custom user types (default: none) - - - typeMappings - Mappings of table.column to Java type (default: none) - - - numericMappings - Mappings of size/digits to Java type (default: none) - - - imports - Array of java imports added to generated query classes: com.bar for package (without .* notation), com.bar.Foo for class (default: empty) - - - generatedAnnotationClass - - The fully qualified class name of the Single-Element Annotation (with String element) to be added on the generated sources. Build in - com.querydsl.core.annotations.Generatedhas CLASS retention which can be used for byte code analysis tools like Jacoco. - (default: javax.annotation.Generated orjavax.annotation.processing.Generated depending on the java version). See also - Single-Element Annotation - - - - -
- - Custom types can be used to register additional Type implementations: - - - com.querydsl.sql.types.InputStreamType - -]]> - - Type mappings can be used to register table.column specific java types: - - - - IMAGE
- CONTENTS - java.io.InputStream -
- -]]>
- - The defaults for the numeric mappings are - - - Numeric mappings - - - - - - Total digits - Decimal digits - Type - - - - - > 18 - 0 - BigInteger - - - > 9 - 0 - Long - - - > 4 - 0 - Integer - - - > 2 - 0 - Short - - - > 0 - 0 - Byte - - - > 0 - > 0 - BigDecimal - - - -
- - They can be customized for specific total/decimal digits combinations like this: - - - - 1 - 0 - java.lang.Byte - - -]]> - - Imports can be used to add cross-schema foreign keys support. - - Schemas, tables and columns can also be renamed using the plugin. Here are some examples: - Renaming a schema: - - - PROD - TEST - - -]]> - - Renaming a table: - - - PROD - CUSTOMER - CSTMR - - -]]> - - Renaming a column: - - - PROD - CUSTOMER - ID - IDX - - -]]> - - Note: fromSchema can be omitted when renaming tables and columns. - - Compared to APT based code generation certain functionality is not available such as QueryDelegate annotation handling. - -
- - - - Code generation via ANT - - - The ANT task com.querydsl.sql.codegen.ant.AntMetaDataExporter - of the querydsl-sql module provides the same functionality as an ANT task. - The configuration parameters of the task are the same as for the Maven plugin, except for the composite types. - - - - The composite types are used without the wrapper element like in this example. - - - - - - - - - - - - -]]> - - - - - - Creating the query types - - To get started export your schema into Querydsl query types like this: - - - - This declares that the database schema is to be mirrored into the - com.myproject.domain package in the target/generated-sources/java folder. - - - - The generated types have the table name transformed to mixed case as the class name and a - similar mixed case transformation applied to the columns which are available as property - paths in the query type. - - - - In addition to this primary key and foreign key constraints are provided as fields - which can be used for compact join declarations. - - - - - - - Configuration - - The configuration is done via the com.querydsl.sql.Configuration class which takes - the - Querydsl SQL dialect as an argument. For H2 you would create it like this - - - - Querydsl uses SQL dialects to customize the SQL serialization needed for - different relational databases. The available dialects are: - - - - - CUBRIDTemplates (tested with CUBRID 8.4) - - - DB2Templates (tested with DB2 10.1.2) - - - DerbyTemplates (tested with Derby 10.8.2.2) - - - FirebirdTemplates (tested with Firebird 2.5) - - - HSQLDBTemplates (tested with HSQLDB 2.2.4) - - - H2Templates (tested with H2 1.3.164) - - - MySQLTemplates (tested with MySQL 5.5) - - - OracleTemplates (test with Oracle 10 and 11) - - - PostgreSQLTemplates (tested with PostgreSQL 9.1) - - - SQLiteTemplates (tested with xerial JDBC 3.7.2) - - - SQLServerTemplates (tested with SQL Server) - - - SQLServer2005Templates (for SQL Server 2005) - - - SQLServer2008Templates (for SQL Server 2008) - - - SQLServer2012Templates (for SQL Server 2012 and later) - - - TeradataTemplates (tested with Teradata 14) - - - - - For customized SQLTemplates instances you can use the builder pattern like this - - - - The methods of the Configuration class can be used to enable direct serialization of literals - via setUseLiterals(true), override schema and tables and register custom types. For full details look - at the javadocs of Configuration. - - - - - - Querying - - For the following examples we will be using the SQLQueryFactory class for query creation. - Using it results in more concise code compared to constructor based query creation. - - - - Querying with Querydsl SQL is as simple as this: - - lastNames = queryFactory.select(customer.lastName).from(customer) - .where(customer.firstName.eq("Bob")) - .fetch(); -]]> - - - which is transformed into the following sql query, assuming that the related table - name is customer - and the columns first_name - and last_name: - - - - - - - - - General usage - - Use the the cascading methods of the SQLQuery class like this - - - select: - Set the projection of the query. (Not necessary if created via query factory) - - - - from: - Add the query sources here. - - - - innerJoin, join, leftJoin, rightJoin, fullJoin, on: - Add join elements using these constructs. - For the join methods the first argument is the join source and the second the target - (alias). - - - - where: - Add query filters, either in varargs form separated via commas or - cascaded via the and-operator. - - - - groupBy: - Add group by arguments in varargs form. - - - - having: - Add having filter of the "group by" grouping as an varags array of - Predicate expressions. - - - - orderBy: - Add ordering of the result as an varargs array of order expressions. - Use asc() and desc() on numeric, string and other comparable expression to access the - OrderSpecifier instances. - - - - limit, offset, restrict: - Set the paging of the result. Limit for max results, - offset for skipping rows and restrict for defining both in one call. - - - - - - - Joins - - Joins are constructed using the following syntax: - - - - and for a left join: - - - - Alternatively the join condition can also be written out: - - - - - - - - - Ordering - - The syntax for declaring ordering is - - - - which is equivalent to the following native SQL - - -SELECT c.first_name, c.last_name -FROM customer c -ORDER BY c.last_name ASC, c.first_name ASC - - - - - - - Grouping - - Grouping can be done in the following form - - - - which is equivalent to the following native SQL - - -SELECT c.last_name -FROM customer c -GROUP BY c.last_name - - - - - - - - - Using Subqueries - - To create a subquery you can use one of the factory methods of SQLExpressions - and add the query parameters via from, where etc. - - - - - Another example - - - - - - - - Selecting literals - - To select literals you need to create constant instances for them like this: - - - - The class com.querydsl.core.types.dsl.Expressions offers also other useful static methods for - projections, operation and template creation. - - - - - - Query extension support - - Custom query extensions to support engine specific syntax can be created by - subclassing AbstractSQLQuery and adding flagging methods like - in the given MySQLQuery example: - - - extends AbstractSQLQuery> { - - public MySQLQuery(Connection conn) { - this(conn, new MySQLTemplates(), new DefaultQueryMetadata()); - } - - public MySQLQuery(Connection conn, SQLTemplates templates) { - this(conn, templates, new DefaultQueryMetadata()); - } - - protected MySQLQuery(Connection conn, SQLTemplates templates, QueryMetadata metadata) { - super(conn, new Configuration(templates), metadata); - } - - public MySQLQuery bigResult() { - return addFlag(Position.AFTER_SELECT, "SQL_BIG_RESULT "); - } - - public MySQLQuery bufferResult() { - return addFlag(Position.AFTER_SELECT, "SQL_BUFFER_RESULT "); - } - - - // ... -} -]]> - - - The flags are custom SQL snippets that can be inserted at specific points in the - serialization. The supported positions are the enums of the - com.querydsl.core.QueryFlag.Position enum class. - - - - - - - Window functions - - Window functions are supported in Querydsl via the methods in the SQLExpressions class. - - Usage example: - - - - - - - - Common table expressions - - Common table expressions are supported in Querydsl SQL via two syntax variants - - - - And using a column listing - - - - If the columns of the common table expression are a subset of an existing table or view - it is advisable to use a generated path type for it, e.g. QEmployee in this case, but if the - columns don't fit any existing table PathBuilder can be used instead. - - Below is an example for such a case - - emp = new PathBuilder(Tuple.class, "emp"); -queryFactory.with(emp, SQLExpressions.select(employee.id, employee.name, employee.departmentId, - department.name.as("departmentName")) - .from(employee) - .innerJoin(department).on(employee.departmentId.eq(department.id)))) - .from(...) -]]> - - - - - - Other SQL expressions - - - Other SQL expressions are also available from the SQLExpressions class as static methods. - - - - - - - Using Data manipulation commands - - - - Insert - - With columns - - - - Without columns - - - - With subquery - - - - With subquery, without columns - - - - As an alternative to the columns/values usage, Querydsl provides also a set - method which can be used like this - - - - which is equivalent to the first example. Usage of the set method always - expands internally to columns and values. - - Beware that - - - - maps the result set of the given query to be inserted whereas - - To get the created keys out instead of modified rows count use one of the executeWithKey/s method. - - - - maps single columns and nulls are used for empty subquery results. - - To populate a clause instance based on the contents of a bean you can use - - - - This will exclude null bindings, if you need also null bindings use - - - - - - - - Update - - With where - - - - Without where - - - - Using bean population - - - - - - - - Delete - - With where - - - - Without where - - - - - - - - - - Batch support in DML clauses - - Querydsl SQL supports usage of JDBC batch updates through the DML APIs. If you - have consecutive DML calls with a similar structure, - you can bundle the the calls via addBatch() usage into one DMLClause. See the examples how - it works for UPDATE, DELETE and INSERT. - - - Update: - - - - Delete: - - - - Insert: - - - - - - - - - Bean class generation - - To create JavaBean DTO types for the tables of your schema use the - MetaDataExporter like this: - - - - Now you can use the bean types as arguments to the populate method in DML - clauses and you can project directly - to bean types in queries. Here is a simple example in JUnit form: - - - - - - - - - - - Extracting the SQL query and bindings - - The SQL query and bindings can be extracted via the getSQL method: - - - - If you need also all literals in the SQL string you can enable literal serialization on the - query or configuration level via setUseLiterals(true). - - - - - - Custom types - - Querydsl SQL provides the possibility to declare custom type mappings for - ResultSet/Statement interaction. The custom type mappings can be - declared in com.querydsl.sql.Configuration instances, which are supplied as constructor - arguments to the actual queries: - - - - - And for a table column - - (Gender.class)); -]]> - - To customize a numeric mapping you can use the registerNumeric method like this - - - - - This will map the Float type to the NUMERIC(5,2) type. - - - - - - Listening to queries and clauses - - SQLListener is a listener interface that can be used to listen to queries and DML clause. SQLListener - instances can be registered either on the configuration and on the query/clause level via the addListener method. - - Use cases for listeners are data synchronization, logging, caching and validation. - - - - - - Spring integration - - Querydsl SQL integrates with Spring through the querydsl-sql-spring module: - - - io.github.openfeign.querydsl - querydsl-sql-spring - ${querydsl.version} - -]]> - - It provides Spring exception translation and a Spring connection provider for usage of Querydsl SQL - with Spring transaction managers. Below is a configuration example: - - - - - - - -
diff --git a/querydsl-docs/src/main/docbook/en-US/legal_notice.xml b/querydsl-docs/src/main/docbook/en-US/legal_notice.xml deleted file mode 100644 index 4fc7c34162..0000000000 --- a/querydsl-docs/src/main/docbook/en-US/legal_notice.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - This copyrighted material is made available to - anyone wishing to use, modify, copy, or redistribute it subject to the terms and conditions of the - Apache License, Version 2.0. - - diff --git a/querydsl-docs/src/main/docbook/media/spatial.png b/querydsl-docs/src/main/docbook/media/spatial.png deleted file mode 100644 index 3a5784c10a..0000000000 Binary files a/querydsl-docs/src/main/docbook/media/spatial.png and /dev/null differ diff --git a/querydsl-docs/src/main/styles/html/custom.xsl b/querydsl-docs/src/main/styles/html/custom.xsl deleted file mode 100644 index ab88ae1f37..0000000000 --- a/querydsl-docs/src/main/styles/html/custom.xsl +++ /dev/null @@ -1,126 +0,0 @@ - - - - -]> - - - - - - - 1 - 0 - 1 - - - - images/ - .gif - - 120 - images/callouts/ - .gif - - - css/stylesheet.css - text/css - book toc,title - - text-align: left - - - - - - - - - - - 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/querydsl-docs/src/main/styles/html/titlepage.xsl b/querydsl-docs/src/main/styles/html/titlepage.xsl deleted file mode 100644 index 09539c068c..0000000000 --- a/querydsl-docs/src/main/styles/html/titlepage.xsl +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - <subtitle/> - <!-- <corpauthor/> - <authorgroup/> - <author/> - <mediaobject/> --> - <othercredit/> - <releaseinfo/> - <copyright/> - <legalnotice/> - <pubdate/> - <revision/> - <revhistory/> - <abstract/> - </t:titlepage-content> - - <t:titlepage-content t:side="verso"> - </t:titlepage-content> - - <t:titlepage-separator> - <hr/> - </t:titlepage-separator> - - <t:titlepage-before t:side="recto"> - </t:titlepage-before> - - <t:titlepage-before t:side="verso"> - </t:titlepage-before> -</t:titlepage> - -</t:templates> diff --git a/querydsl-docs/src/main/styles/html_single/custom.xsl b/querydsl-docs/src/main/styles/html_single/custom.xsl deleted file mode 100644 index a9b9c698ae..0000000000 --- a/querydsl-docs/src/main/styles/html_single/custom.xsl +++ /dev/null @@ -1,126 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<!-- - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. ---> -<!DOCTYPE xsl:stylesheet [ - <!ENTITY db_xsl_path "http://docbook.sourceforge.net/release/xsl/current"> -]> -<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" - xmlns:xslthl="http://xslthl.sf.net" - exclude-result-prefixes="xslthl" - version='1.0'> - - <xsl:import href="&db_xsl_path;/html/docbook.xsl"/> - <xsl:import href="&db_xsl_path;/html/highlight.xsl"/> - -<!-- Extensions --> - <xsl:param name="use.extensions">1</xsl:param> - <xsl:param name="tablecolumns.extension">0</xsl:param> - <xsl:param name="callout.extensions">1</xsl:param> - -<!-- Activate Graphics --> - <xsl:param name="admon.graphics" select="1"/> - <xsl:param name="admon.graphics.path">images/</xsl:param> - <xsl:param name="admon.graphics.extension">.gif</xsl:param> - <xsl:param name="callout.graphics" select="1" /> - <xsl:param name="callout.defaultcolumn">120</xsl:param> - <xsl:param name="callout.graphics.path">images/callouts/</xsl:param> - <xsl:param name="callout.graphics.extension">.gif</xsl:param> - - <xsl:param name="table.borders.with.css" select="1"/> - <xsl:param name="html.stylesheet">css/stylesheet.css</xsl:param> - <xsl:param name="html.stylesheet.type">text/css</xsl:param> - <xsl:param name="generate.toc">book toc,title</xsl:param> - - <xsl:param name="admonition.title.properties">text-align: left</xsl:param> - -<!-- Label Chapters and Sections (numbering) --> - <xsl:param name="chapter.autolabel" select="1"/> - <xsl:param name="section.autolabel" select="1"/> - <xsl:param name="section.autolabel.max.depth" select="3"/> - - <xsl:param name="section.label.includes.component.label" select="1"/> - <xsl:param name="table.footnote.number.format" select="'1'"/> - -<!-- Show only Sections up to level 3 in the TOCs --> - <xsl:param name="toc.section.depth">3</xsl:param> - -<!-- Remove "Chapter" from the Chapter titles... --> - <xsl:param name="local.l10n.xml" select="document('')"/> - <l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0"> - <l:l10n language="en"> - <l:context name="title-numbered"> - <l:template name="chapter" text="%n. %t"/> - <l:template name="section" text="%n %t"/> - </l:context> - </l:l10n> - </l:i18n> - -<!-- Use code syntax highlighting --> - <xsl:param name="highlight.source" select="1"/> - - <xsl:template match='xslthl:keyword'> - <span class="hl-keyword"><xsl:value-of select='.'/></span> - </xsl:template> - - <xsl:template match='xslthl:comment'> - <span class="hl-comment"><xsl:value-of select='.'/></span> - </xsl:template> - - <xsl:template match='xslthl:oneline-comment'> - <span class="hl-comment"><xsl:value-of select='.'/></span> - </xsl:template> - - <xsl:template match='xslthl:multiline-comment'> - <span class="hl-multiline-comment"><xsl:value-of select='.'/></span> - </xsl:template> - - <xsl:template match='xslthl:tag'> - <span class="hl-tag"><xsl:value-of select='.'/></span> - </xsl:template> - - <xsl:template match='xslthl:attribute'> - <span class="hl-attribute"><xsl:value-of select='.'/></span> - </xsl:template> - - <xsl:template match='xslthl:value'> - <span class="hl-value"><xsl:value-of select='.'/></span> - </xsl:template> - - <xsl:template match='xslthl:string'> - <span class="hl-string"><xsl:value-of select='.'/></span> - </xsl:template> - - <!-- fixes --> - - <xsl:template match='xslthl:annotation'> - <span class="hl-annotation"><xsl:apply-templates/></span> - </xsl:template> - - <xsl:template match='xslthl:number'> - <span class="hl-value"><xsl:apply-templates/></span> - </xsl:template> - - <xsl:template match='xslthl:doccomment'> - <xsl:apply-templates/> - </xsl:template> - - - -</xsl:stylesheet> diff --git a/querydsl-docs/src/main/styles/html_single/titlepage.xsl b/querydsl-docs/src/main/styles/html_single/titlepage.xsl deleted file mode 100644 index 09539c068c..0000000000 --- a/querydsl-docs/src/main/styles/html_single/titlepage.xsl +++ /dev/null @@ -1,61 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<!-- - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. ---> - -<t:templates xmlns:t="http://nwalsh.com/docbook/xsl/template/1.0" - xmlns:param="http://nwalsh.com/docbook/xsl/template/1.0/param" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> - -<!-- ==================================================================== --> - -<t:titlepage t:element="book" t:wrapper="div" class="titlepage"> - <t:titlepage-content t:side="recto"> - <productname/> - <title/> - <subtitle/> - <!-- <corpauthor/> - <authorgroup/> - <author/> - <mediaobject/> --> - <othercredit/> - <releaseinfo/> - <copyright/> - <legalnotice/> - <pubdate/> - <revision/> - <revhistory/> - <abstract/> - </t:titlepage-content> - - <t:titlepage-content t:side="verso"> - </t:titlepage-content> - - <t:titlepage-separator> - <hr/> - </t:titlepage-separator> - - <t:titlepage-before t:side="recto"> - </t:titlepage-before> - - <t:titlepage-before t:side="verso"> - </t:titlepage-before> -</t:titlepage> - -</t:templates> diff --git a/querydsl-docs/src/main/styles/pdf/custom.xsl b/querydsl-docs/src/main/styles/pdf/custom.xsl deleted file mode 100644 index 120ce5d0c1..0000000000 --- a/querydsl-docs/src/main/styles/pdf/custom.xsl +++ /dev/null @@ -1,528 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<!-- - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. ---> -<!DOCTYPE xsl:stylesheet [ - <!ENTITY db_xsl_path "http://docbook.sourceforge.net/release/xsl/current"> -]> -<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" - xmlns:fo="http://www.w3.org/1999/XSL/Format" - xmlns:xslthl="http://xslthl.sf.net" - exclude-result-prefixes="xslthl" - version='1.0'> - - <xsl:import href="&db_xsl_path;/fo/docbook.xsl"/> - - <xsl:import href="&db_xsl_path;/fo/highlight.xsl"/> - -<!-- Use nice graphics for admonitions --> - <xsl:param name="admon.graphics">'1'</xsl:param> - <xsl:param name="admon.graphics.path">@file.prefix@@dbf.xsl@/images/</xsl:param> - <xsl:param name="draft.watermark.image" select="'@file.prefix@@dbf.xsl@/images/draft.png'"/> - <xsl:param name="paper.type" select="'@paper.type@'"/> - - <xsl:param name="page.margin.top" select="'1cm'"/> - <xsl:param name="region.before.extent" select="'1cm'"/> - <xsl:param name="body.margin.top" select="'1.5cm'"/> - - <xsl:param name="body.margin.bottom" select="'1.5cm'"/> - <xsl:param name="region.after.extent" select="'1cm'"/> - <xsl:param name="page.margin.bottom" select="'1cm'"/> - <xsl:param name="title.margin.left" select="'0cm'"/> - -<!--################################################### - Header - ################################################### --> - -<!-- More space in the center header for long text --> - <xsl:attribute-set name="header.content.properties"> - <xsl:attribute name="font-family"> - <xsl:value-of select="$body.font.family"/> - </xsl:attribute> - <xsl:attribute name="margin-left">-5em</xsl:attribute> - <xsl:attribute name="margin-right">-5em</xsl:attribute> - </xsl:attribute-set> - -<!--################################################### - Table of Contents - ################################################### --> - - <xsl:param name="generate.toc"> - book toc,title - </xsl:param> - -<!--################################################### - Custom Header - ################################################### --> - - <xsl:template name="header.content"> - <xsl:param name="pageclass" select="''"/> - <xsl:param name="sequence" select="''"/> - <xsl:param name="position" select="''"/> - <xsl:param name="gentext-key" select="''"/> - - <xsl:variable name="Version"> - <xsl:choose> - <xsl:when test="//productname"> - <xsl:value-of select="//productname"/><xsl:text> </xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>please define productname in your docbook file!</xsl:text> - </xsl:otherwise> - </xsl:choose> - </xsl:variable> - - <xsl:choose> - <xsl:when test="$sequence='blank'"> - <xsl:choose> - <xsl:when test="$position='center'"> - <xsl:value-of select="$Version"/> - </xsl:when> - - <xsl:otherwise> - <!-- nop --> - </xsl:otherwise> - </xsl:choose> - </xsl:when> - - <xsl:when test="$pageclass='titlepage'"> - <!-- nop: other titlepage sequences have no header --> - </xsl:when> - - <xsl:when test="$position='center'"> - <xsl:value-of select="$Version"/> - </xsl:when> - - <xsl:otherwise> - <!-- nop --> - </xsl:otherwise> - </xsl:choose> - </xsl:template> - -<!--################################################### - Custom Footer - ################################################### --> - - <xsl:template name="footer.content"> - <xsl:param name="pageclass" select="''"/> - <xsl:param name="sequence" select="''"/> - <xsl:param name="position" select="''"/> - <xsl:param name="gentext-key" select="''"/> - - <xsl:variable name="Version"> - <xsl:choose> - <xsl:when test="//releaseinfo"> - <xsl:value-of select="//releaseinfo"/> - </xsl:when> - <xsl:otherwise> - <!-- nop --> - </xsl:otherwise> - </xsl:choose> - </xsl:variable> - - <xsl:variable name="Title"> - <xsl:value-of select="//title"/> - </xsl:variable> - - <xsl:choose> - <xsl:when test="$sequence='blank'"> - <xsl:choose> - <xsl:when test="$double.sided != 0 and $position = 'left'"> - <xsl:value-of select="$Version"/> - </xsl:when> - - <xsl:when test="$double.sided = 0 and $position = 'center'"> - <!-- nop --> - </xsl:when> - - <xsl:otherwise> - <fo:page-number/> - </xsl:otherwise> - </xsl:choose> - </xsl:when> - - <xsl:when test="$pageclass='titlepage'"> - <!-- nop: other titlepage sequences have no footer --> - </xsl:when> - - <xsl:when test="$double.sided != 0 and $sequence = 'even' and $position='left'"> - <fo:page-number/> - </xsl:when> - - <xsl:when test="$double.sided != 0 and $sequence = 'odd' and $position='right'"> - <fo:page-number/> - </xsl:when> - - <xsl:when test="$double.sided = 0 and $position='right'"> - <fo:page-number/> - </xsl:when> - - <xsl:when test="$double.sided != 0 and $sequence = 'odd' and $position='left'"> - <xsl:value-of select="$Version"/> - </xsl:when> - - <xsl:when test="$double.sided != 0 and $sequence = 'even' and $position='right'"> - <xsl:value-of select="$Version"/> - </xsl:when> - - <xsl:when test="$double.sided = 0 and $position='left'"> - <xsl:value-of select="$Version"/> - </xsl:when> - - <xsl:when test="$position='center'"> - <xsl:value-of select="$Title"/> - </xsl:when> - - <xsl:otherwise> - <!-- nop --> - </xsl:otherwise> - </xsl:choose> - </xsl:template> - - <xsl:template match="processing-instruction('hard-pagebreak')"> - <fo:block break-before='page'/> - </xsl:template> - -<!--################################################### - Extensions - ################################################### --> - -<!-- These extensions are required for table printing and other stuff --> - <xsl:param name="use.extensions">1</xsl:param> - <xsl:param name="tablecolumns.extension">0</xsl:param> - <xsl:param name="callout.extensions">1</xsl:param> - <xsl:param name="fop.extensions">1</xsl:param> - -<!--################################################### - Paper & Page Size - ################################################### --> - -<!-- Paper type, no headers on blank pages, no double sided printing --> - <xsl:param name="double.sided">0</xsl:param> - <xsl:param name="headers.on.blank.pages">0</xsl:param> - <xsl:param name="footers.on.blank.pages">0</xsl:param> - -<!--################################################### - Fonts & Styles - ################################################### --> - - <xsl:param name="hyphenate">false</xsl:param> - -<!-- Default Font size --> - <xsl:param name="body.font.master">11</xsl:param> - <xsl:param name="body.font.small">8</xsl:param> - -<!-- Line height in body text --> - <xsl:param name="line-height">1.4</xsl:param> - -<!-- Chapter title size --> - <xsl:attribute-set name="chapter.titlepage.recto.style"> - <xsl:attribute name="text-align">left</xsl:attribute> - <xsl:attribute name="font-weight">bold</xsl:attribute> - <xsl:attribute name="font-size"> - <xsl:value-of select="$body.font.master * 1.8"/> - <xsl:text>pt</xsl:text> - </xsl:attribute> - </xsl:attribute-set> - -<!-- Why is the font-size for chapters hardcoded in the XSL FO templates? - Let's remove it, so this sucker can use our attribute-set only... --> - <xsl:template match="title" mode="chapter.titlepage.recto.auto.mode"> - <fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format" - xsl:use-attribute-sets="chapter.titlepage.recto.style"> - <xsl:call-template name="component.title"> - <xsl:with-param name="node" select="ancestor-or-self::chapter[1]"/> - </xsl:call-template> - </fo:block> - </xsl:template> - - <!-- Start each chapter on a new page --> - <xsl:attribute-set name="chapter.title.properties"> - <xsl:attribute name="break-before">page</xsl:attribute> - </xsl:attribute-set> - -<!-- Sections 1, 2 and 3 titles have a small bump factor and padding --> - <xsl:attribute-set name="section.title.level1.properties"> - <xsl:attribute name="space-before.optimum">0.8em</xsl:attribute> - <xsl:attribute name="space-before.minimum">0.8em</xsl:attribute> - <xsl:attribute name="space-before.maximum">0.8em</xsl:attribute> - <xsl:attribute name="font-size"> - <xsl:value-of select="$body.font.master * 1.5"/> - <xsl:text>pt</xsl:text> - </xsl:attribute> - <xsl:attribute name="space-after.optimum">0.1em</xsl:attribute> - <xsl:attribute name="space-after.minimum">0.1em</xsl:attribute> - <xsl:attribute name="space-after.maximum">0.1em</xsl:attribute> - </xsl:attribute-set> - <xsl:attribute-set name="section.title.level2.properties"> - <xsl:attribute name="space-before.optimum">0.6em</xsl:attribute> - <xsl:attribute name="space-before.minimum">0.6em</xsl:attribute> - <xsl:attribute name="space-before.maximum">0.6em</xsl:attribute> - <xsl:attribute name="font-size"> - <xsl:value-of select="$body.font.master * 1.25"/> - <xsl:text>pt</xsl:text> - </xsl:attribute> - <xsl:attribute name="space-after.optimum">0.1em</xsl:attribute> - <xsl:attribute name="space-after.minimum">0.1em</xsl:attribute> - <xsl:attribute name="space-after.maximum">0.1em</xsl:attribute> - </xsl:attribute-set> - <xsl:attribute-set name="section.title.level3.properties"> - <xsl:attribute name="space-before.optimum">0.4em</xsl:attribute> - <xsl:attribute name="space-before.minimum">0.4em</xsl:attribute> - <xsl:attribute name="space-before.maximum">0.4em</xsl:attribute> - <xsl:attribute name="font-size"> - <xsl:value-of select="$body.font.master * 1.0"/> - <xsl:text>pt</xsl:text> - </xsl:attribute> - <xsl:attribute name="space-after.optimum">0.1em</xsl:attribute> - <xsl:attribute name="space-after.minimum">0.1em</xsl:attribute> - <xsl:attribute name="space-after.maximum">0.1em</xsl:attribute> - </xsl:attribute-set> - -<!-- Use code syntax highlighting --> - <xsl:param name="highlight.source" select="1"/> - <xsl:param name="highlight.default.language" select="xml" /> - - <xsl:template match='xslthl:keyword'> - <fo:inline font-weight="bold" color="#7F0055"><xsl:apply-templates/></fo:inline> - </xsl:template> - - <xsl:template match='xslthl:comment'> - <fo:inline font-style="italic" color="#3F5F5F"><xsl:apply-templates/></fo:inline> - </xsl:template> - - <xsl:template match='xslthl:oneline-comment'> - <fo:inline font-style="italic" color="#3F5F5F"><xsl:apply-templates/></fo:inline> - </xsl:template> - - <xsl:template match='xslthl:multiline-comment'> - <fo:inline font-style="italic" color="#3F5FBF"><xsl:apply-templates/></fo:inline> - </xsl:template> - - <xsl:template match='xslthl:tag'> - <fo:inline color="#3F7F7F"><xsl:apply-templates/></fo:inline> - </xsl:template> - - <xsl:template match='xslthl:attribute'> - <fo:inline color="#7F007F"><xsl:apply-templates/></fo:inline> - </xsl:template> - - <xsl:template match='xslthl:value'> - <fo:inline color="#2A00FF"><xsl:apply-templates/></fo:inline> - </xsl:template> - - <xsl:template match='xslthl:string'> - <fo:inline color="#2A00FF"><xsl:apply-templates/></fo:inline> - </xsl:template> - - <!-- fixes --> - - <xsl:template match='xslthl:annotation'> - <xsl:apply-templates/> - </xsl:template> - - <xsl:template match='xslthl:number'> - <fo:inline color="#2A00FF"><xsl:apply-templates/></fo:inline> - </xsl:template> - -<!--################################################### - Tables - ################################################### --> - - <!-- Some padding inside tables --> - <xsl:attribute-set name="table.cell.padding"> - <xsl:attribute name="padding-left">4pt</xsl:attribute> - <xsl:attribute name="padding-right">4pt</xsl:attribute> - <xsl:attribute name="padding-top">4pt</xsl:attribute> - <xsl:attribute name="padding-bottom">4pt</xsl:attribute> - </xsl:attribute-set> - -<!-- Only hairlines as frame and cell borders in tables --> - <xsl:param name="table.frame.border.thickness">0.1pt</xsl:param> - <xsl:param name="table.cell.border.thickness">0.1pt</xsl:param> - -<!--################################################### - Labels - ################################################### --> - -<!-- Label Chapters and Sections (numbering) --> - <xsl:param name="chapter.autolabel" select="1"/> - <xsl:param name="section.autolabel" select="1"/> - <xsl:param name="section.autolabel.max.depth" select="1"/> - - <xsl:param name="section.label.includes.component.label" select="1"/> - <xsl:param name="table.footnote.number.format" select="'1'"/> - -<!--################################################### - Programlistings - ################################################### --> - -<!-- Verbatim text formatting (programlistings) --> - <xsl:attribute-set name="monospace.verbatim.properties"> - <xsl:attribute name="font-size"> - <xsl:value-of select="$body.font.small * 1.0"/> - <xsl:text>pt</xsl:text> - </xsl:attribute> - </xsl:attribute-set> - - <xsl:attribute-set name="verbatim.properties"> - <xsl:attribute name="space-before.minimum">1em</xsl:attribute> - <xsl:attribute name="space-before.optimum">1em</xsl:attribute> - <xsl:attribute name="space-before.maximum">1em</xsl:attribute> - <xsl:attribute name="space-after.minimum">0.1em</xsl:attribute> - <xsl:attribute name="space-after.optimum">0.1em</xsl:attribute> - <xsl:attribute name="space-after.maximum">0.1em</xsl:attribute> - - <xsl:attribute name="border-color">#444444</xsl:attribute> - <xsl:attribute name="border-style">solid</xsl:attribute> - <xsl:attribute name="border-width">0.1pt</xsl:attribute> - <xsl:attribute name="padding-top">0.5em</xsl:attribute> - <xsl:attribute name="padding-left">0.5em</xsl:attribute> - <xsl:attribute name="padding-right">0.5em</xsl:attribute> - <xsl:attribute name="padding-bottom">0.5em</xsl:attribute> - <xsl:attribute name="margin-left">0.5em</xsl:attribute> - <xsl:attribute name="margin-right">0.5em</xsl:attribute> - <xsl:attribute name="keep-together.within-page">always</xsl:attribute> - </xsl:attribute-set> - - <!-- Shade (background) programlistings --> - <xsl:param name="shade.verbatim">1</xsl:param> - <xsl:attribute-set name="shade.verbatim.style"> - <xsl:attribute name="background-color">#F0F0F0</xsl:attribute> - </xsl:attribute-set> - - <xsl:attribute-set name="list.block.spacing"> - <xsl:attribute name="space-before.optimum">0.1em</xsl:attribute> - <xsl:attribute name="space-before.minimum">0.1em</xsl:attribute> - <xsl:attribute name="space-before.maximum">0.1em</xsl:attribute> - <xsl:attribute name="space-after.optimum">0.1em</xsl:attribute> - <xsl:attribute name="space-after.minimum">0.1em</xsl:attribute> - <xsl:attribute name="space-after.maximum">0.1em</xsl:attribute> - </xsl:attribute-set> - - <xsl:attribute-set name="example.properties"> - <xsl:attribute name="space-before.minimum">0.5em</xsl:attribute> - <xsl:attribute name="space-before.optimum">0.5em</xsl:attribute> - <xsl:attribute name="space-before.maximum">0.5em</xsl:attribute> - <xsl:attribute name="space-after.minimum">0.1em</xsl:attribute> - <xsl:attribute name="space-after.optimum">0.1em</xsl:attribute> - <xsl:attribute name="space-after.maximum">0.1em</xsl:attribute> - <xsl:attribute name="keep-together.within-column">always</xsl:attribute> - </xsl:attribute-set> - -<!--################################################### - Title information for Figures, Examples etc. - ################################################### --> - - <xsl:attribute-set name="formal.title.properties" use-attribute-sets="normal.para.spacing"> - <xsl:attribute name="font-weight">normal</xsl:attribute> - <xsl:attribute name="font-style">italic</xsl:attribute> - <xsl:attribute name="font-size"> - <xsl:value-of select="$body.font.master"/> - <xsl:text>pt</xsl:text> - </xsl:attribute> - <xsl:attribute name="hyphenate">false</xsl:attribute> - <xsl:attribute name="space-before.minimum">0.1em</xsl:attribute> - <xsl:attribute name="space-before.optimum">0.1em</xsl:attribute> - <xsl:attribute name="space-before.maximum">0.1em</xsl:attribute> - </xsl:attribute-set> - -<!--################################################### - Callouts - ################################################### --> - -<!-- don't use images for callouts --> - <xsl:param name="callout.graphics">0</xsl:param> - <xsl:param name="callout.unicode">1</xsl:param> - -<!-- Place callout marks at this column in annotated areas --> - <xsl:param name="callout.defaultcolumn">90</xsl:param> - -<!--################################################### - Misc - ################################################### --> - -<!-- Placement of titles --> - <xsl:param name="formal.title.placement"> - figure after - example after - equation before - table before - procedure before - </xsl:param> - -<!-- Format Variable Lists as Blocks (prevents horizontal overflow) --> - <xsl:param name="variablelist.as.blocks">1</xsl:param> - - <xsl:param name="body.start.indent">0pt</xsl:param> - -<!-- Show only Sections up to level 3 in the TOCs --> - <xsl:param name="toc.section.depth">3</xsl:param> - -<!-- Remove "Chapter" from the Chapter titles... --> - <xsl:param name="local.l10n.xml" select="document('')"/> - <l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0"> - <l:l10n language="en"> - <l:context name="title-numbered"> - <l:template name="chapter" text="%n. %t"/> - <l:template name="section" text="%n %t"/> - </l:context> - <l:context name="title"> - <l:template name="example" text="Example %n %t"/> - </l:context> - </l:l10n> - </l:i18n> - -<!--################################################### - colored and hyphenated links - ################################################### --> - - <xsl:template match="ulink"> - <fo:basic-link external-destination="{@url}" - xsl:use-attribute-sets="xref.properties" - text-decoration="underline" - color="blue"> - <xsl:choose> - <xsl:when test="count(child::node())=0"> - <xsl:value-of select="@url"/> - </xsl:when> - <xsl:otherwise> - <xsl:apply-templates/> - </xsl:otherwise> - </xsl:choose> - </fo:basic-link> - </xsl:template> - - <xsl:template match="link"> - <fo:basic-link internal-destination="{@linkend}" - xsl:use-attribute-sets="xref.properties" - text-decoration="underline" - color="blue"> - <xsl:choose> - <xsl:when test="count(child::node())=0"> - <xsl:value-of select="@linkend"/> - </xsl:when> - <xsl:otherwise> - <xsl:apply-templates/> - </xsl:otherwise> - </xsl:choose> - </fo:basic-link> - </xsl:template> - -</xsl:stylesheet> \ No newline at end of file diff --git a/querydsl-docs/src/main/styles/pdf/titlepage.xsl b/querydsl-docs/src/main/styles/pdf/titlepage.xsl deleted file mode 100644 index dc18e1e0de..0000000000 --- a/querydsl-docs/src/main/styles/pdf/titlepage.xsl +++ /dev/null @@ -1,101 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<!-- - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. ---> - -<!DOCTYPE t:templates [ -<!ENTITY hsize0 "10pt"> -<!ENTITY hsize1 "12pt"> -<!ENTITY hsize2 "14.4pt"> -<!ENTITY hsize3 "17.28pt"> -<!ENTITY hsize4 "20.736pt"> -<!ENTITY hsize5 "24.8832pt"> -<!ENTITY hsize0space "7.5pt"> <!-- 0.75 * hsize0 --> -<!ENTITY hsize1space "9pt"> <!-- 0.75 * hsize1 --> -<!ENTITY hsize2space "10.8pt"> <!-- 0.75 * hsize2 --> -<!ENTITY hsize3space "12.96pt"> <!-- 0.75 * hsize3 --> -<!ENTITY hsize4space "15.552pt"> <!-- 0.75 * hsize4 --> -<!ENTITY hsize5space "18.6624pt"> <!-- 0.75 * hsize5 --> -]> -<t:templates xmlns:t="http://nwalsh.com/docbook/xsl/template/1.0" - xmlns:param="http://nwalsh.com/docbook/xsl/template/1.0/param" - xmlns:fo="http://www.w3.org/1999/XSL/Format" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> - - <t:titlepage t:element="book" t:wrapper="fo:block"> - <t:titlepage-content t:side="recto"> - <title - t:named-template="division.title" - param:node="ancestor-or-self::book[1]" - text-align="center" - font-size="&hsize5;" - space-before="&hsize5space;" - font-weight="bold" - font-family="{$title.fontset}"/> - <subtitle - text-align="center" - font-size="&hsize4;" - space-before="&hsize4space;" - font-family="{$title.fontset}"/> - - <!-- <corpauthor space-before="0.5em" - font-size="&hsize2;"/> - <authorgroup space-before="0.5em" - font-size="&hsize2;"/> - <author space-before="0.5em" - font-size="&hsize2;"/> --> - - <mediaobject space-before="2em" space-after="2em"/> - <releaseinfo space-before="5em" font-size="&hsize2;"/> - <copyright space-before="1.5em" - font-weight="normal" - font-size="8"/> - <legalnotice space-before="5em" - font-weight="normal" - font-style="italic" - font-size="8"/> - <othercredit space-before="2em" - font-weight="normal" - font-size="8"/> - <pubdate space-before="0.5em"/> - <revision space-before="0.5em"/> - <revhistory space-before="0.5em"/> - <abstract space-before="0.5em" - text-align="start" - margin-left="0.5in" - margin-right="0.5in" - font-family="{$body.fontset}"/> - </t:titlepage-content> - - <t:titlepage-content t:side="verso"> - </t:titlepage-content> - - <t:titlepage-separator> - </t:titlepage-separator> - - <t:titlepage-before t:side="recto"> - </t:titlepage-before> - - <t:titlepage-before t:side="verso"> - </t:titlepage-before> -</t:titlepage> - -<!-- ==================================================================== --> - -</t:templates>