SQL Builder is a Java library for dealing with dynamic SQL. SQL Builder offers three groups of functionality:

Builders

Builders simplify the creation of SQL strings. They know a little bit about SQL syntax, and make the creation of dynamic SQL a little nicer in Java. Like Java’s StringBuilder, they use chainable calls. Here’s an example of using SelectBuilder.

1 new SelectBuilder()
2 .column("name")
3 .column("age")
4 .from("Employee")
5 .where("dept = 'engineering'")
6 .where("salary > 100000")
7 .toString();

This produces the SQL string select name, age from Employee where dept = 'engineering' and salary > 100000. Note how SelectBuilder knows to join the columns with a comma and to join the where clauses with and.

In addition to SelectBuilder, SQL Builder provides builders for insert, update, and delete statements.

WARNING: builders DO NOT attempt to perform any SQL escaping. You have to be careful to escape any externally-provided strings or your application may be vulnerable to a SQL injection attack.

For example, suppose you implement the following:

1 String sql = new SelectBuilder()
2 .column("firstName")
3 .from("Employee")
4 .where("id = " + id);
5 
6 // execute the SQL on a database connection

If the value for id came from a URL, an attacker could provide a corrupted value like this: 0; drop table Employee;. Depending on how you execute the SQL, you could find yourself with no more employee records.

Fortunately, SQL Builder provides a mechanism called a creator that neatly solves this problem.

Creators

Each builder class has a corresponding Creator class that implements the PreparedStatmentCreator interface. SQL Builder repackages versions of the PreparedStatementCreator and JdbcTemplate from Spring JDBC to make it simple to execute dynamically-created SQL statements when given a data source:

1 PreparedStatementCreator psc =
2     new UpdateCreator("Employee")
3     .setValue("name", "Bob");
4 
5 new JdbcTemplate(dataSource).update(psc);

One big advantage of creators over builders is that you can inject data into the executed SQL in a way that is safe from SQL injection. The unsafe example from the builders section can be re-implemented safely using a SelectCreator:

1 SelectCreator sc = new SelectCreator()
2 .column("firstName")
3 .from("Employee")
4 .where("id = :id")
5 .setParameter("id", id);
6 
7 return new JdbcTemplate(dataSource).query(sc);

In this example, the creator creates the prepared statement select firstName from Employee where id = ?, and uses the JDBC driver to safely escape the value of id.

One nice thing about creators is that you can call their methods in any order you like, and they’ll still produce the correct SQL. For example, consider the common case where different queries can be performed based on the presence of requested parameters.

1 SelectCreator sc = new SelectCreator()
2 .column("name")
3 .column("age")
4 .from("Employee e");
5 
6 if (deptId != null) {
7     sc.where(eq("e.deptId", deptId));
8 }

You can even conditionally join other tables:

1 if (deptName != null) {
2     sc
3     .column("d.name as deptName")
4     .join("Dept d on e.deptId = d.id")
5     .where(eq("d.name", deptName));
6 }

Predicates

A predicate is a small class that encapsulates adding an expression to a creator’s where clause and setting the appropriate parameters. SQL Builder provides a number of predicates in the Predicates class. The most commonly used predicate is the equality predicate, eq:

1 import static ca.krasnay.sqlbuilder.Predicates.eq;
2 
3 new SelectCreator()
4 .column("firstName")
5 .from("Employee")
6 .where(eq("id", id));

Here, the two step process of adding a string to the where clause and separately calling setParameter from the previous example is replaced with a neat invocation of the eq predicate.

Below is another example where a predicate can save a tricky bit of work, especially when the passed string of department IDs can vary in length:

1 import static ca.krasnay.sqlbuilder.Predicates.in;
2 
3 List<Integer> deptIds = //...
4 
5 new SelectCreator()
6 .column("firstName")
7 .from("Employee")
8 .where(in("deptId", deptIds));

You can easily implement your own predicates. Here is the implementation of the Predicates.eq method as an example:

 1 public static Predicate eq(final String expr, final Object value) {
 2     return new Predicate() {
 3         private String param;
 4         public void init(AbstractSqlCreator creator) {
 5             param = creator.allocateParameter();
 6             creator.setParameter(param, value);
 7         }
 8         public String toSql() {
 9             return String.format("%s = :%s", expr, param);
10         }
11     };
12 }

Object-Relational Mapping

SQL Builder implements a simple object-relational mapping tool. Unlike some more complicated ORM tools such as Hibernate and JPA, SQL Builder’s ORM makes some simplifying assumptions:

Maven

Add the following dependency to your POM:

1 <dependency>
2   <groupId>ca.krasnay</groupId>
3   <artifactId>sqlbuilder</artifactId>
4   <version>1.2</version>
5 </dependency>

SQL Builder depends on slf4j and Spring JDBC, so be sure to add the desired versions of these to your <dependencyManagement> section.