Skip to content
This repository has been archived by the owner on Jan 6, 2023. It is now read-only.

Latest commit

 

History

History
136 lines (95 loc) · 4.24 KB

README.md

File metadata and controls

136 lines (95 loc) · 4.24 KB

JDBI-ST4

Provides an easy way to externalize SQL statements for JDBI (2.x) in StringTemplate 4 StringTemplate Group Files.

Usage

Getting It

Use Maven:

<dependency>
  <groupId>org.jdbi.v2</groupId>
  <artifactId>jdbi-st4</artifactId>
  <version>...</version>
</dependency>

Latest version can be found by searching.

SQL Object API

This library is typically used to externalize SQL into StringTemplate Group Files. Take the following example Dao:

package org.jdbi.v2.st4;

@UseST4StatementLocator
public interface Dao {

    @SqlUpdate
    void createSomethingTable();

    @SqlUpdate
    int insertSomething(int id, String name);

    @SqlQuery
    @MapResultAsBean
    Something findById(int id, @Define("columns") String... columns);

    @SqlQuery("select concat('Hello, ', name, '!') from something where id = :0")
    String findGreetingFor(int id);
}

The @UseST4StatementLocator annotation tells JDBI to use the ST4StatementLocator for this object. By default, it looks for a stringtemplate group file on the classpath at /com/example/Dao.sql.stg. Basically, it looks for <ClassName>.sql.stg in the same package as <ClassName>. With a maven project, you'd achieve this by putting it in src/main/resources/com/example/<ClassName>.sql.stg.

If we look at the stringtemplate group file:

createSomethingTable() ::= <%
    create table something (id int primary key, name varchar)
%>

insertSomething() ::= <%
    insert into something (id, name) values (:0, :1)
%>

findById(columns) ::= <%
    select < columns; separator="," > from something where id = :0
%>

We can then exercise it:

DBI dbi = new DBI(h2);
Dao dao = dbi.onDemand(Dao.class);

dao.createSomethingTable();
dao.insertSomething(7, "Jan");
dao.insertSomething(1, "Brian");

Something jan = dao.findById(7, "id", "name");
assertThat(jan.getId()).as("Jan's ID").isEqualTo(7);
assertThat(jan.getName()).as("Jan's Name").isEqualTo("Jan");

Something partial = dao.findById(7, "name");
assertThat(partial.getId()).as("Jan's ID").isEqualTo(0); // default int value
assertThat(partial.getName()).as("Jan's Name").isEqualTo("Jan");

String greeting = dao.findGreetingFor(7);
assertThat(greeting).isEqualTo("Hello, Jan!");

We find a template defined for each method. You can override this by naming the template to use in the @SqlUpdate or @SqlQuery annotation. For example, using @SqlQuery("woof") would look for a template named woof in that group.

For the findById(columns) template, we need to pass in the columns we want to template into the SQL. We make them available to the template by putting them on the StatementContext in JDBI. The easiest way to do this is with the @Define annotation on another parameter, which we do here. However, values set on the Handle or DBI will also be available.

Finally, note that if a template is not found (such as for findGreetingFor the "name" (sql literal in this case)) is compiled as a string template and evaluated.

Fluent API

We can use the same mechanisms with the fluent api, though in this case we have to tell JDBI where to find the stringtemplate group, as there is no object to use as the basis:

DBI dbi = new DBI(h2);
dbi.setStatementLocator(ST4StatementLocator.fromClasspath("/org/jdbi/st4/ExampleTest.Dao.sql.stg"));

dbi.useHandle((h) -> {
    h.execute("createSomethingTable");

    int numCreated = h.createStatement("insertSomething")
                      .bind("0", 0)
                      .bind("1", "Jan")
                      .execute();
    assertThat(numCreated).as("number of rows inserted").isEqualTo(1);

    String name = h.createQuery("findById")
                  .bind("0", 0)
                  .define("columns", "name")
                  .mapTo(String.class)
                  .first();
    assertThat(name).as("Jan's Name").isEqualTo("Jan");
});

In this case we set the template group as the same one from the sql object example. There are a few ways to specify which to use, check out the factory methods and their javadocs on ST4StatementLocator to explore.

License

Apache License 2.0