Query beans
Query beans are optional but they provide a nice way to write queries with type safe
compile time checking
. They are also easy to use and learn with IDE auto-completion
on properties and expressions.
Query beans are generated using a Java annotation processing (APT) or Kotlin annotation processing (KAPT).
For each entity a query bean is generated with the same name but prefixed with Q
.
So for an entity bean called Customer there is a query bean generated called QCustomer.
When the entity bean model changes the query beans are regenerated and as developers we get compile time checking on our application queries - we get a compile time error if our queries are no longer valid for the model.
Examples:
Contact contact =
new QContact() // Contact query bean
.email.equalTo("rob@foo.com") // type safe expression
.findOne(); // with IDE auto-completion
List<Customer> customers =
new QCustomer() // Customer query bean
.status.equalTo(Status.NEW)
.billingAddress.city.equalTo("Auckland") // joins automatically added
.contacts.isEmpty() // to support expressions
.findList();
APT / KAPT (generating query beans)
To generate Java
query beans we use the io.ebean:querybean-generator
java annotation processor and to generate Kotlin
query beans we use
io.ebean:kotlin-querybean-generator.
Generating with Maven
Refer to docs / getting-started / maven for details of how to generate query beans using maven.
Generating with Gradle
Refer to docs / getting-started / gradle for details of how to generate query beans using gradle.
Enhancement
Note that prior to version 12.1.8 we need to edit a src/main/resources/ebean.mf
manifest file to specify querybean-packages
for the packages that should
be enhanced for query beans. This is no longer needed from 12.1.8 onwards.
Example (Pre 12.1.8)
entity-packages: org.example.domain
transactional-packages: org.example
querybean-packages: org.example
Caveat - refactor rename
Refactor rename entity bean
When we refactor rename an entity bean in an IDE the query beans we should trigger a build all
.
This is because the query beans for the old bean names are kept around until the next build all
.
Once we do a build all
this will effectively delete the old query beans and generate the new ones.
At this point we get compiler errors for the queries that we need to adjust (use the new query bean names).
Groovy Spock
When using query beans with Groovy perhaps in Spock tests we need to use them inside a @CompileStatic
block.
@CompileStatic
static def findCount(String name) {
return new QDbSample().name.eq(name).findCount()
}
Then we can use the helper method in our spock test like:
...
then:
// this line NPEs
findCount('fred') == 1