我正在尝试编写一个Spring Boot Controller,允许用户对Postgres数据库进行任意SELECT查询并查看结果。我通过使用链接中的a form实现了这一点。该项目基于this starter app。
码:
@Controller
@SpringBootApplication
public class Main {
@Value("${spring.datasource.url}")
private String dbUrl;
@Autowired
private DataSource dataSource;
public static void main(String[] args) throws Exception {
SpringApplication.run(Main.class, args);
}
@GetMapping("/query")
public String queryForm(Model model) {
model.addAttribute("query", new Query());
return "query";
}
@PostMapping("/query")
public String querySubmit(@ModelAttribute Query query) {
try (final Connection connection = dataSource.getConnection()) {
final Statement stmt = connection.createStatement();
final String rawQueryContent = query.getContent().trim();
final String queryContent;
if(!rawQueryContent.toLowerCase().contains("limit")) {
queryContent = rawQueryContent + " LIMIT 500";
} else {
queryContent = rawQueryContent;
}
final ResultSet rs = stmt.executeQuery(queryContent);
final StringBuilder sb = new StringBuilder();
while (rs.next()) {
sb.append("Row #" + rs.getRow() + ": " + rs.toString() + "\n");
}
query.setContent(sb.toString());
rs.close();
stmt.closeOnCompletion();
} catch (Exception e) {
query.setContent(e.getMessage());
}
return "queryresult";
}
@Bean
public DataSource dataSource() throws SQLException {
if (dbUrl == null || dbUrl.isEmpty()) {
return new HikariDataSource();
} else {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(dbUrl);
return new HikariDataSource(config);
}
}
}
表单如下所示:
但我得到的输出看起来像这样:
Row 1: HikariProxyResultSet@188463256 wrapping org.postgresql.jdbc.PgResultSet@ff61f7d
Row 2: HikariProxyResultSet@188463256 wrapping org.postgresql.jdbc.PgResultSet@ff61f7d
Row 3: HikariProxyResultSet@188463256 wrapping org.postgresql.jdbc.PgResultSet@ff61f7d
Row 4: HikariProxyResultSet@188463256 wrapping org.postgresql.jdbc.PgResultSet@ff61f7d
这不是我想要的!我想查看数据库中的实际行,如:
Row 1: "Dave" | 23 | "Philadelphia"
Row 2: "Anne" | 72 | "New York"
Row 3: "Susie" | 44 | "San Francisco"
Row 4: "Alex" | 22 | "Miami"
哎呀,我宁愿得到我在手工输入SQL到数据库时通常得到的原始字符串输出,而不是ResultSet内存中的地址。
如何在不事先知道表中的列数或列类型的情况下获取实际的数据库输出?
我建议,初学者通过使用JdbcTemplate
结合ResultSetExtractor
简化代码来简化代码。您可以使用ResultSet
本身来获取结果的列数。
我也不确定你为什么要重新定义DataSource
。
总而言之,下面的代码应该可以做到这一点(没有测试过它并从头顶输入它,所以可能需要一些抛光)。
@Controller
@SpringBootApplication
public class Main {
@Autowired
private JdbcTemplate jdbc;
public static void main(String[] args) throws Exception {
SpringApplication.run(Main.class, args);
}
@GetMapping("/query")
public String queryForm(Model model) {
model.addAttribute("query", new Query());
return "query";
}
@PostMapping("/query")
public String querySubmit(@ModelAttribute Query query) {
final String rawQueryContent = query.getContent().trim();
final String queryContent;
if(!rawQueryContent.toLowerCase().contains("limit")) {
queryContent = rawQueryContent + " LIMIT 500";
} else {
queryContent = rawQueryContent;
}
String content = jdbc.query(queryContent, new ResultSetExtractor<StringBuilder>() {
public StringBuilder extractData(ResultSet rs) {
StringBuilder sb = new StringBuilder();
int columns = rs.getMetaData().getColumnCount();
while (rs.next()) {
int row = rs.getRow();
sb.append(rs.getRow()).append('|');
for (int i = 1 ; i <= columns ; i++) {
sb.append(rs.getObject(i)).append('|');
}
}
return sb.toString();
}
});
query.setContent(content);
return "queryresult";
}
}
另请参阅How to get the number of columns from a JDBC ResultSet?了解如何获取列数。