问题描述
我有一个Vaadin 14应用程序,该应用程序从Postgresql 11数据库检索数据。 将Java 8与9.4-1202-jdbc42一起使用。
我尝试实现数据库表的下载功能。我创建了一个带有以下代码片段的按钮。它正在运行,我可以下载示例数据。
StreamResource resource = new StreamResource("foo.csv",() -> new ByteArrayInputStream("foo,foo2,foo3\nboo,boo2,boo3".getBytes()));
Button button = new Button("Click to download");
FileDownloadWrapper buttonWrapper = new FileDownloadWrapper(resource);
buttonWrapper.wrapComponent(button);
add(buttonWrapper);
但是我想从Postgresql数据库下载数据,而不是一些静态输入。因此,我使用copyManager(org.postgresql.copy.copyManager)进行“ copY ... TO STDOUT”请求。
String sql = "SELECT * FROM table";
copyManager.copyOut("copY (" + sql + ") TO STDOUT WITH (FORMAT CSV,HEADER)",outputStream);
编辑: 现在可以创建StreamResource,但是Postgresql不喜欢我的sql语句。 当前,此操作仅使用表头创建一个空的csv。
copyOut copiedData = copyManager.copyOut(sqlRequest);
ByteArrayInputStream stream = new ByteArrayInputStream(copiedData.readFromcopy());
return new StreamResource("foo.csv",() -> stream);
Postgresql对PgAdmin中相同的sql请求的响应:
copY (SELECT * FROM table) TO STDOUT WITH (FORMAT CSV,HEADER)
ERROR: can't execute copY TO: use the copy_to() method instead
如果我将STDOUT替换为文件名,则可以在PgAdmin中使用
copY (SELECT * FROM table) TO 'D:\test.csv' WITH (FORMAT CSV,HEADER);
copY 63
Query returned successfully in 881 msec.
尽管我知道在PgAdmin控制台中使用STDOUT并没有多大意义,但它应该可以通过JDBC使用,对吧?
我的sql语句怎么了?我找不到有关copy_to()方法的任何好信息。
解决方法
您可以使用OpenCSV library从ResultSet中创建CSV文件,而不是直接从数据库查询中创建CSV文件。
但是,您实际上并不需要文件系统中的物理文件。甚至还有一些潜在的严重弊端-文件吃光了有限的磁盘空间,I / O昂贵,并且有可能意外地将一个用户的文件链接到另一个用户。 StreamResource
接受任何类型的输入流,因此最好将整个操作都保留在内存中,而无需中间的物理文件。