Use declarative interfaces for Java database queries.

Quick Start

Gradle Configuration

Set up dependencies for the annotation processor and runtime. Add a JSON file with configuration for the annotation processor, and tell the annotation processor the path. TODO: milestone2 - gradle plugin to help with this.

src/main/resources/kiwi-config.json
{
    "dataSources": {
        "default": {
            "named": "default",
            "url": "jdbc:postgresql://localhost:5432/example?user=example",
            "database": "example",
            "username":  "example"
        }
    },
    "dependencyInjectionStyle": "JAKARTA",
    "debug": false
}
Groovy
def kiwiversion = "0.1"
dependencies {
    annotationProcessor("org.ethelred.kiwiproc:processor:$kiwiversion")
    implementation("org.ethelred.kiwiproc:runtime:$kiwiversion")
    implementation("jakarta.inject:jakarta.inject-api:2.0.1")
}

tasks.withType(JavaCompile).configureEach {
    options.compilerArgs.add("-Aorg.ethelred.kiwiproc.configuration=src/main/resources/kiwi-config.json")
}
Kotlin
val kiwiversion = "0.1"
dependencies {
    annotationProcessor("org.ethelred.kiwiproc:processor:$kiwiversion")
    implementation("org.ethelred.kiwiproc:runtime:$kiwiversion")
    implementation("jakarta.inject:jakarta.inject-api:2.0.1")
}

tasks.withType<JavaCompile>().configureEach {
    options.compilerArgs.add("-Aorg.ethelred.kiwiproc.configuration=src/main/resources/kiwi-config.json")
}

Define a DAO interface

@DAO (1)
public interface CountryCityDao {
    @SqlQuery("""
            SELECT id, name, code
            FROM country
            WHERE code = :code
            """) (2)
    @Nullable
    Country findCountryByCode(String code);

    @SqlUpdate("""
            INSERT INTO city(name, country_id)
            VALUES (:name, :country_id)
            """)
    boolean addCity(String name, int countryId);

}
1 Declare an interface as being a DAO.
2 Define a query. The SQL statement goes inline with the code. Parameters are inserted with ':'.

Inject

Use your favourite dependency injection framework to inject an instance of your DAO.

Framework Support

Kiwiproc uses only the Jakarta annotations @Singleton and @Named, so should work with any Dependency Injection framework that supports those. It expects a DataSource to be injected, with a name matching that specified on the @DAO annotation.

  • Micronaut test cases are in the "test-micronaut" subproject.

  • Spring test cases are on the roadmap.

Database Support

Kiwiproc is currently only tested with Postgresql. Support for SQL Arrays is known to be specific to Postgresql. Other databases using standard JDBC may work, as long as you don’t use Arrays.