当前位置: 首页 > 知识库问答 >
问题:

在获取多行时使用spring-jdbctemplate的csv输出

贺奕
2023-03-14

我正在使用spring jdbctemplate与Oracle数据库交互。为了获取给定条件下的多行,我希望将结果存储在以列名作为标题的csv文件中。

我试过几种方法-

或者我们可以通过任何其他方法来实现同样的目的,而不需要手动从ResultSet中获取每个记录并将其设置为逗号分隔的字符串并存储在文件中。

共有1个答案

孔理
2023-03-14

此代码保存查询结果并将其返回为csv文件(您可以使用endpoint下载)。但是,如果您不需要在控制器中返回给用户,则很容易将所有数据转发到FileOutputStream

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;

@RestController
@RequestMapping("/api/report")
public class UserReportController {
    private JdbcTemplate jdbcTemplate;

    public UserReportController(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    private static String ALL_USERS_QUERY = "select * from users";

    @GetMapping("/all-users")
    public void allUsers(HttpServletResponse response) throws IOException {
        response.setContentType("text/csv");
        jdbcTemplate.query(ALL_USERS_QUERY, new StreamingCsvResultSetExtractor(response.getOutputStream()));
    }


    class StreamingCsvResultSetExtractor
        implements ResultSetExtractor<Void> {

        private char DELIMITER = ',';

        private final OutputStream os;

        
        public StreamingCsvResultSetExtractor(final OutputStream os) {
            this.os = os;
        }

        @Override
        public Void extractData(final ResultSet rs) {
            try (PrintWriter pw = new PrintWriter(os, true)) {
                final ResultSetMetaData rsmd = rs.getMetaData();
                final int columnCount = rsmd.getColumnCount();
                writeHeader(rsmd, columnCount, pw);
                while (rs.next()) {
                    for (int i = 1; i <= columnCount; i++) {
                        final Object value = rs.getObject(i);
                        String strValue = value == null ? "" : value.toString();
                        pw.write(strValue.contains(",") ? "\"" + strValue+ "\"" : strValue);
                        if (i != columnCount) {
                            pw.append(DELIMITER);
                        }
                    }
                    pw.println();
                }
                pw.flush();
            } catch (final SQLException e) {
                throw new RuntimeException(e);
            }
            return null;
        }

        private void writeHeader(final ResultSetMetaData rsmd,
                                 final int columnCount, final PrintWriter pw) throws SQLException {
            for (int i = 1; i <= columnCount; i++) {
                pw.write(rsmd.getColumnName(i));
                if (i != columnCount) {
                    pw.append(DELIMITER);
                }
            }
            pw.println();
        }
    }

}
 类似资料:
  • 我使用的是Spring的(Spring版本4.1.4)。对于我的类“JdbcTemplate”实例,我正在将select查询作为一个准备好的语句。但是,我的查询意外地没有返回任何结果。因此,我确实需要调试我的查询,并确保查询是我期望的。 如何取回作为< code>JdbcTemplate的内部< code>PreparedStatement的一部分对数据库执行的实际SQL? 我熟悉使用预制语句的

  • 问题内容: 如何使用在mySQL上运行的JdbcTemplate以可扩展的方式执行以下SQL 。在这种情况下,可伸缩意味着: 服务器上仅执行一条SQL语句 它适用于任何数量的行。 声明如下: 假设我有一个带有和字段的POJO列表。我意识到我可以遍历列表并执行: 但这并不能满足第一个条件。 我相信我也可以执行: 但是据我所知,这只会编译一次SQL并多次执行它,从而再次使第一个条件失败。 似乎通过了这

  • 我使用Spring初始化器、嵌入式Tomcat、Thymeleaf模板引擎和作为可执行JAR文件的包生成了一个Spring Boot web应用程序。 使用的技术: 错误:

  • 1. 前言 如果我们的项目非常简单,仅仅是对数据库几张表进行简单的增删改查操作,那么实际上直接使用 JDBC 操作数据库就可以了。 由于 JDBC 中有很多模板代码,每次都是加载驱动 - 建立数据库连接 - 查询或操作数据库 - 关闭数据库连接这样的模板代码, Spring 提供了 JdbcTemplate 对原生 JDBC 进行了简单的封装。 本篇文章,我们来实现一个完整的、基于 Spring

  • 我正在开发一个需要在大型机上调用DB2函数以获取id的应用程序。 在spring应用程序上下文中,我定义了jdbc模板来查询zOS上的DB2: 然后,我将数据源定义如下: 以上工作。然而,看看ibm的db2jcc内部。jar文件中,我看到了一个用于连接池的datasource类-com。ibm。db2.jcc。DB2ConnectionPoolDataSource。所以我试着用它来代替上面的一个,