Sie können auch a ResultSetExtractor
anstelle von a verwenden RowMapper
. Beide sind genauso einfach wie die anderen, der einzige Unterschied ist, dass Sie anrufen ResultSet.next()
.
public String test() {
String sql = "select ID_NMB_SRZ from codb_owner.TR_LTM_SLS_RTN "
+ " where id_str_rt = '999' and ID_NMB_SRZ = '60230009999999'";
return jdbc.query(sql, new ResultSetExtractor<String>() {
@Override
public String extractData(ResultSet rs) throws SQLException,
DataAccessException {
return rs.next() ? rs.getString("ID_NMB_SRZ") : null;
}
});
}
Das ResultSetExtractor
hat den zusätzlichen Vorteil, dass Sie alle Fälle behandeln können, in denen mehr als eine Zeile oder keine Zeilen zurückgegeben werden.
UPDATE : Einige Jahre später habe ich ein paar Tricks zu teilen.JdbcTemplate
funktioniert hervorragend mit Java 8 Lambdas, für die die folgenden Beispiele entwickelt wurden, aber Sie können ganz einfach eine statische Klasse verwenden, um dasselbe zu erreichen.
Während es sich um einfache Typen handelt, dienen diese Beispiele als Leitfaden für den allgemeinen Fall des Extrahierens von Domänenobjekten.
Zuerst. Nehmen wir an, Sie haben der Einfachheit halber ein Kontoobjekt mit zwei Eigenschaften Account(Long id, String name)
. Sie möchten wahrscheinlich ein RowMapper
Objekt für diese Domain haben.
private static final RowMapper<Account> MAPPER_ACCOUNT =
(rs, i) -> new Account(rs.getLong("ID"),
rs.getString("NAME"));
Sie können diesen Mapper jetzt direkt in einer Methode verwenden, um Account
Domänenobjekte aus einer Abfrage ( jt
ist eine JdbcTemplate
Instanz) zuzuordnen .
public List<Account> getAccounts() {
return jt.query(SELECT_ACCOUNT, MAPPER_ACCOUNT);
}
Großartig, aber jetzt wollen wir unser ursprüngliches Problem und verwenden meine ursprüngliche Lösung RowMapper
, um das Mapping für uns durchzuführen.
public Account getAccount(long id) {
return jt.query(
SELECT_ACCOUNT,
rs -> rs.next() ? MAPPER_ACCOUNT.mapRow(rs, 1) : null,
id);
}
Großartig, aber dies ist ein Muster, das Sie möglicherweise und möglicherweise wiederholen möchten. Sie können also eine generische Factory-Methode erstellen, um eine neue ResultSetExtractor
für die Aufgabe zu erstellen .
public static <T> ResultSetExtractor singletonExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? mapper.mapRow(rs, 1) : null;
}
Das Erstellen eines ResultSetExtractor
Jetzt wird trivial.
private static final ResultSetExtractor<Account> EXTRACTOR_ACCOUNT =
singletonExtractor(MAPPER_ACCOUNT);
public Account getAccount(long id) {
return jt.query(SELECT_ACCOUNT, EXTRACTOR_ACCOUNT, id);
}
Ich hoffe, dies hilft zu zeigen, dass Sie Teile jetzt ganz einfach auf leistungsstarke Weise kombinieren können, um Ihre Domain einfacher zu gestalten.
UPDATE 2 : Kombinieren Sie mit einem optional für optionale Werte statt null.
public static <T> ResultSetExtractor<Optional<T>> singletonOptionalExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? Optional.of(mapper.mapRow(rs, 1)) : Optional.empty();
}
Was jetzt, wenn es verwendet wird, Folgendes haben könnte:
private static final ResultSetExtractor<Optional<Double>> EXTRACTOR_DISCOUNT =
singletonOptionalExtractor(MAPPER_DISCOUNT);
public double getDiscount(long accountId) {
return jt.query(SELECT_DISCOUNT, EXTRACTOR_DISCOUNT, accountId)
.orElse(0.0);
}
ResultSet.next()
würden, dies ebenfalls unnötig aufgerufen würde. Die Verwendung von aResultSetExtractor
ist in diesem Fall ein viel effizienteres Werkzeug.