O/R-Mapping ohne Schnickschnack

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.

Links

https://java.net/projects/eodsql

Kommentare sind abgeschaltet.