35

我想知道从表中选择记录的最佳做法是什么。我在下面提到了两种方法,我想知道哪一种是使用 Spring JdbcTemplate从表中选择数据的最佳实践。

第一个例子

try {
    String sql = "SELECT id FROM tableName WHERE column_name = '" + coulmn value + "'";

    long id = jdbcTemplate.queryForObject(sql, Long.class);
} catch (Exception e) {
    if (log.isDebugEnabled()) {
        log.debug(e);
    }
}

这会引发以下异常:

预期 1 实际 0 喜欢

当表不包含任何数据时。我的朋友告诉我,这不是选择数据的最佳做法。他建议下面提到的代码是选择数据的唯一最佳实践。

第二个例子

try {
    String countQuery = "SELECT COUNT(id) FROM tableName";

    int count = jdbcTemplate.queryForInt(countQuery);
    if (count > 0) {
        String sql = "SELECT id FROM tableName WHERE column_name = '" + coulmn value + "'";

        long id = jdbcTemplate.queryForObject(sql, Long.class);
    }
} catch (Exception e) {
    if (log.isDebugEnabled()) {
        log.debug(e);
    }
}


我很想知道正确的一种或任何其他最佳做法。

4

4 回答 4

38

绝对第一种方式是最佳实践,因为在第二种方式中,您会两次访问数据库,而实际上您应该只访问一次。这可能会导致性能问题。

您需要做的是捕获异常EmptyResultDataAccessException,然后返回 null。如果Spring JDBC 模板在数据库中找不到数据,则它会抛出EmptyResultDataAccessException异常。

您的代码应如下所示。

try {
     sql = "SELECT id FROM tableNmae WHERE column_name ='"+ coulmn value+ "'";
     id= jdbcTemplate.queryForObject(sql, Long.class);
} 
catch (EmptyResultDataAccessException e) {
   if(log.isDebugEnabled()){
       log.debug(e);
   }
   return null
}
于 2013-08-29T06:46:58.390 回答
7

我面临类似的情况,并在使用 ResultSetExtractor 而不是 RowMapper 时找到了更清洁的解决方案

jdbcTemplate.query(DBConstants.GET_VENDOR_DOCUMENT, new Object[]{vendorid}, rs -> {

            if(rs.next()){
                DocumentPojo vendorDoc = new DocumentPojo();
                vendorDoc.setRegDocument(rs.getString("registrationdoc"));
                vendorDoc.setMsmeLetter(rs.getString("msmeletter"));
                vendorDoc.setProprietorshipDocument(rs.getString("propertiershipformat"));
                vendorDoc.setNeftDocument(rs.getString("neftdoc"));
                vendorDoc.setPanCardDocument(rs.getString("pancard"));
                vendorDoc.setCancelledChequeDoc(rs.getString("cheque"));
                return vendorDoc;
            }
            else {
                return null;
            }

    });

如果从数据库中没有找到结果,我为结果集设置了一个 if 条件并返回空引用。所以,我不需要尝试捕获代码并将两个查询传递给数据库。

ResultSetExtractor(在这种情况下)的主要优点是使用ResultsetExtractor,您需要自己遍历结果集,比如在while循环中。

更多点可以在这里找到

于 2017-03-21T14:18:52.720 回答
5

这是 queryForObject 方法源代码

@Nullable
public <T> T queryForObject(String sql, RowMapper<T> rowMapper) throws 
DataAccessException {
    List<T> results = this.query(sql, rowMapper);
    return DataAccessUtils.nullableSingleResult(results);
}

DataAccessUtils.nullableSingleResult

    @Nullable
public static <T> T nullableSingleResult(@Nullable Collection<T> results) throws IncorrectResultSizeDataAccessException {
    if (CollectionUtils.isEmpty(results)) {
        throw new EmptyResultDataAccessException(1);
    } else if (results.size() > 1) {
        throw new IncorrectResultSizeDataAccessException(1, results.size());
    } else {
        return results.iterator().next();
    }
}

不知道为什么他们在空集合上抛出异常,可能这只是上面方法的复制粘贴

    public static <T> T requiredSingleResult(@Nullable Collection<T> results) throws IncorrectResultSizeDataAccessException {
    if (CollectionUtils.isEmpty(results)) {
        throw new EmptyResultDataAccessException(1);
    } else if (results.size() > 1) {
        throw new IncorrectResultSizeDataAccessException(1, results.size());
    } else {
        return results.iterator().next();
    }
}

比他们应该使用的方法多一步

    @Nullable
public static <T> T singleResult(@Nullable Collection<T> results) throws IncorrectResultSizeDataAccessException {
    if (CollectionUtils.isEmpty(results)) {
        return null;
    } else if (results.size() > 1) {
        throw new IncorrectResultSizeDataAccessException(1, results.size());
    } else {
        return results.iterator().next();
    }
}

现在解决方案帮助了我:扩展 JdbcTemlate 类(您可以使用注入的 DataSource 构造它)并覆盖 queryForObject 方法:

    @Nullable
public <T> T queryForObject(String sql, RowMapper<T> rowMapper) throws DataAccessException {
    List<T> results = this.query(sql, rowMapper);
    return DataAccessUtils.singleResult(results);
}

现在使用您的实现不要忘记检查它是否适用于春季版本更新(恕我直言不太可能)

于 2018-07-18T08:46:30.543 回答
2

在查询中使用 ifNull 的更好方法,所以如果有 null 那么你得到 0 例如 -

sql = "SELECT ifNull(id,0) FROM tableName WHERE column_name ='"+ coulmn value+ "'";

使用这种方式,您可以获得默认值 0 否则您的 Id

于 2016-05-23T11:53:52.117 回答