Bạn cũng có thể sử dụng a ResultSetExtractor
thay vì a RowMapper
. Cả hai đều dễ dàng như nhau, sự khác biệt duy nhất là bạn gọi 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;
}
});
}
Các ResultSetExtractor
có thêm lợi ích mà bạn có thể xử lý tất cả trường hợp có nhiều hơn một hàng hoặc không có hàng trả lại.
CẬP NHẬT : Vài năm trôi qua và tôi có một vài thủ thuật để chia sẻ. JdbcTemplate
hoạt động tuyệt vời với java 8 lambdas mà các ví dụ sau đây được thiết kế cho nhưng bạn có thể khá dễ dàng sử dụng một lớp tĩnh để đạt được điều tương tự.
Mặc dù câu hỏi là về các kiểu đơn giản, nhưng những ví dụ này đóng vai trò là hướng dẫn cho trường hợp phổ biến là trích xuất các đối tượng miền.
Trước hết. Hãy giả sử rằng bạn có một đối tượng tài khoản với hai thuộc tính để đơn giản hóa Account(Long id, String name)
. Bạn có thể muốn có một RowMapper
đối tượng miền này.
private static final RowMapper<Account> MAPPER_ACCOUNT =
(rs, i) -> new Account(rs.getLong("ID"),
rs.getString("NAME"));
Bây giờ bạn có thể sử dụng trình ánh xạ này trực tiếp trong một phương pháp để ánh xạ Account
các đối tượng miền từ một truy vấn ( jt
là một JdbcTemplate
phiên bản).
public List<Account> getAccounts() {
return jt.query(SELECT_ACCOUNT, MAPPER_ACCOUNT);
}
Tuyệt vời, nhưng bây giờ chúng tôi muốn vấn đề ban đầu của mình và chúng tôi sử dụng giải pháp ban đầu của tôi, sử dụng lại giải pháp RowMapper
để thực hiện ánh xạ cho chúng tôi.
public Account getAccount(long id) {
return jt.query(
SELECT_ACCOUNT,
rs -> rs.next() ? MAPPER_ACCOUNT.mapRow(rs, 1) : null,
id);
}
Tuyệt vời, nhưng đây là một mô hình mà bạn có thể và sẽ muốn lặp lại. Vì vậy, bạn có thể tạo một phương thức nhà máy chung để tạo một phương thức mới ResultSetExtractor
cho nhiệm vụ.
public static <T> ResultSetExtractor singletonExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? mapper.mapRow(rs, 1) : null;
}
Tạo một ResultSetExtractor
bây giờ trở nên tầm thường.
private static final ResultSetExtractor<Account> EXTRACTOR_ACCOUNT =
singletonExtractor(MAPPER_ACCOUNT);
public Account getAccount(long id) {
return jt.query(SELECT_ACCOUNT, EXTRACTOR_ACCOUNT, id);
}
Tôi hy vọng điều này sẽ giúp cho bạn thấy rằng giờ đây bạn có thể dễ dàng kết hợp các phần một cách hiệu quả để làm cho miền của bạn đơn giản hơn.
CẬP NHẬT 2 : Kết hợp với một Tùy chọn cho các giá trị tùy chọn thay vì null.
public static <T> ResultSetExtractor<Optional<T>> singletonOptionalExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? Optional.of(mapper.mapRow(rs, 1)) : Optional.empty();
}
Mà bây giờ khi được sử dụng có thể có những điều sau đây:
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()
sẽ được gọi là không cần thiết. Sử dụng aResultSetExtractor
là một công cụ hiệu quả hơn nhiều trong trường hợp này.