Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用SpringJDBCTemplate选择数据的最佳实践_Java_Spring_Jdbctemplate - Fatal编程技术网

Java 使用SpringJDBCTemplate选择数据的最佳实践

Java 使用SpringJDBCTemplate选择数据的最佳实践,java,spring,jdbctemplate,Java,Spring,Jdbctemplate,我想知道从表中选择记录的最佳实践是什么。我在下面提到了两种方法,我想知道哪种方法是使用Spring从表中选择数据的最佳实践 第一个例子 这将引发以下异常: 预期为1实际为0 当表不包含任何数据时。我的朋友告诉我,这不是选择数据的最佳做法。他建议,下面提到的代码是选择数据的唯一最佳实践 第二个例子 我很想知道正确的方法或任何其他最佳实践。第一种方法肯定是最佳实践,因为第二种方法是两次访问数据库,实际上应该只访问一次。这可能会导致性能问题 您需要做的是捕获异常EmptyResultDataAcce

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

第一个例子 这将引发以下异常:

预期为1实际为0

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

第二个例子

我很想知道正确的方法或任何其他最佳实践。

第一种方法肯定是最佳实践,因为第二种方法是两次访问数据库,实际上应该只访问一次。这可能会导致性能问题

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

您的代码应该如下所示

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
}

在查询中使用ifNull的更好方法因此,如果存在null,则得到0 例如-


使用这种方法,您可以获得默认值0,否则您的Id将面临类似的情况,并且在使用ResultSetTextRactor而不是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;
            }

    });
若并没有从数据库中找到结果,那个么我已经为resultset设置了一个If条件并返回null引用。所以,我不需要尝试捕获代码并向数据库传递两个查询

ResultSetTextRactor(在本场景中)的主要优点是使用ResultSetTextRactor,您需要自己迭代结果集,比如在while循环中。


更多要点可以在这里找到

这是查询对象方法的源代码

@Nullable
public <T> T queryForObject(String sql, RowMapper<T> rowMapper) throws 
DataAccessException {
    List<T> results = this.query(sql, rowMapper);
    return DataAccessUtils.nullableSingleResult(results);
}
@Nullable
公共T queryForObject(字符串sql、行映射器行映射器)抛出
DataAccessException{
List results=this.query(sql,行映射器);
返回DataAccessUtils.nullableSingleResult(结果);
}
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();
    }
}
@Nullable
公共静态T nullableSingleResult(@Nullable Collection results)引发IncorrectResultSizeDataAccessException{
if(CollectionUtils.isEmpty(结果)){
抛出新的EmptyResultDataAccessException(1);
}else if(results.size()>1){
抛出新的IncorrectResultSizeDataAccessException(1,results.size());
}否则{
返回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();
    }
}
public static T requiredSingleResult(@Nullable Collection results)引发不正确的SultSizeDataAccessException{
if(CollectionUtils.isEmpty(结果)){
抛出新的EmptyResultDataAccessException(1);
}else if(results.size()>1){
抛出新的IncorrectResultSizeDataAccessException(1,results.size());
}否则{
返回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();
    }
}
@Nullable
公共静态T singleResult(@Nullable Collection results)引发IncorrectResultSizeDataAccessException{
if(CollectionUtils.isEmpty(结果)){
返回null;
}else if(results.size()>1){
抛出新的IncorrectResultSizeDataAccessException(1,results.size());
}否则{
返回results.iterator().next();
}
}
现在,解决方案帮助了我: 扩展JdbcTemlate类(您可以通过注入数据源来构造它) 并覆盖queryForObject方法:

    @Nullable
public <T> T queryForObject(String sql, RowMapper<T> rowMapper) throws DataAccessException {
    List<T> results = this.query(sql, rowMapper);
    return DataAccessUtils.singleResult(results);
}
@Nullable
公共T queryForObject(字符串sql、行映射器行映射器)引发DataAccessException{
List results=this.query(sql,行映射器);
返回DataAccessUtils.singleResult(结果);
}
现在,使用您的实现
别忘了检查它是否适用于spring版本更新(不太可能是IMHO)

很抱歉这么说,但两者都不是最佳实践;)虽然Dhanush的答案是确定的,但查询的字符串连接是错误的!这只会导致sql注入攻击,而且由于无法缓存查询语句,因此会降低性能。请看一看(命名)参数以解决这两个问题。@MartinFrey-你说得对。字符串连接不是最佳实践。我的意图是指出问题中给出的两种方法之间的区别:)我正因为这个问题而挠头。你帮我解决了。谢谢如果我们捕获到
EmptyResultDataAccessException
,那么整个事务不是在Spring之前回滚了吗?如何摆脱它?例如,假设我们正在同一事务中对db运行几个其他查询/更新,其中一个查询/更新抛出
EmptyResultDataAccessException
@Munish Chandel-Spring在默认情况下会在发生RuntimeException时回滚。当捕获EmptyResultDataAccessException(这是一个RuntimeException)时,不会发生RuntimeException,事务将成功。顺便说一句,OP没有提到事务……我认为这是行不通的,因为空的ResultSet没有空值。调用rs.next()不会在JDBC模板移动光标一次后再次向前移动光标,导致缺少第一行吗?问题是,获取一行。对于多行,我们可以使用rs.hasNext选项
    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();
    }
}
    @Nullable
public <T> T queryForObject(String sql, RowMapper<T> rowMapper) throws DataAccessException {
    List<T> results = this.query(sql, rowMapper);
    return DataAccessUtils.singleResult(results);
}