Zwischen der Flexibilität reinen SQLs und der Mächtigkeit ausgewachsener O/R-Mapper existiert eine kleine Bibliothek, die es beinahe in das JDK 6 geschafft hätte: EoD SQL (Ease of Development SQL). Die Idee hinter EoD SQL ist so genial wie einfach: Der Nutzer annotiert ein Java-Interface mit SQL-Statements und die Bibliothek liefert mittels eines Java-Reflection-Proxys eine Implementierung dieses Interfaces zur Benutzung:
public interface NutzerMgmt extends BaseQuery {
@Select("SELECT COUNT(*) FROM USER")
long ermittleNutzerAnzahl();
}
Folglich die Benutzung :
Connection c = … ;
NutzerMgmt nutzerMgmt = QueryTool.getQuery(c, NutzerMgmt.class);
try {
long anzahl = nutzerMgmt.ermittleNutzerAnzahl();
} finally {
nutzerMgmt.close(); // schließt ebenfalls die Connection
}
Möchte man das Gleiche mit reinem SQL erreichen, so ist der Code ungleich komplizierter:
try {
Connection connection = DriverManager.getConnection(…);
try {
Statement statement = connection.createStatement();
try {
ResultSet result = statement.executeQuery(
"SELECT COUNT(*) FROM USER");
long anzahl = result.getLong(1);
} finally {
// schließt auch das ResultSet
if (statement != null) statement.close();
} finally {
if (connection != null) connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
Statt einfach die SQL-Query auszuführen, ist man mehr mit Exception-Handling beschäftigt. EoD SQL wirft erfreulicherweise nur Runtime-Exceptions.
Die eigentliche Funktionalität von EoD SQL beruht jedoch auf der Fähigkeit, Java-Beans auf SQL-Statements zu mappen.
public class Nutzer {
@ResultColumn("LOGIN")
private String login;
@ResultColumn("CREATED")
private Date angelegtAm;
// Getter- und Setter-Methoden
}
Um einen Nutzer über sein Login zu erhalten, definiert man in obigem Nutzer-Management-Interface das Folgende:
@Select("SELECT * FROM USER WHERE LOGIN = ?{1}")
Nutzer findeNutzerPerLogin(String login);
Auch die Rückgabe einer Liste ist möglich:
@Select("SELECT * FROM USER"+
" WHERE CREATED >= ?{1}"+
" ORDER BY CREATED")
List<Nutzer> findeNutzerPerErzeugtSeit(Date erzeugtSeit);
Alle SQL-Statements werden ohne syntaktische/semantische Prüfung in Prepared-Statements transformiert. Ein Insert- oder Update-Statement bedeutet deshalb etwas mehr Arbeit:
@Update("INSERT INTO USER (LOGIN, CREATED)"+
" VALUES (?{1.login}, ?{1.angelegtAm})")
void erzeugeNutzer(Nutzer nutzer);
EoD SQL bietet alle Funktionalität, die in diesem Kontext zu erwarten wäre:
- Transaktionen, Save-Points
- Nutzung von DataSources
- Ansprechen von Stored-Procedures
- Auto-Increment-Primärschlüssel
- Paging
- Setter-Access statt Field-Access
Der Einsatz der EoD SQL Bibliothek ist erfreulich unkompliziert, da keine weiteren Laufzeit-Abhängigkeiten zu beachten sind; es muss weder ein Java-Agent konfiguriert werden, noch geschieht irgendeine Bytecode-Magie. Der Reflection-Proxy-Ansatz ermöglicht es darüber hinaus relativ unkompliziert, Interzeptoren an Abfragen zu heften, um so im Bedarfsfall Result-Caching, State-Tracking, Validierung oder Auditing zu realisieren. EoD SQL stößt allerdings an seine Grenzen, wenn es um das Mapping von Objekt-Graphen geht. Ebenso wenig lassen sich Map-Strukturen anstelle von Java-Beans verwenden. Für reine CRUD-Anwendungen mit Master-Detail-Ansichten ist EoD SQL jedoch eine hervorragende Wahl.


