Я пытаюсь написать Spring Boot Controller, который позволяет пользователю делать произвольные запросы SELECT к базе данных Postgres и видеть результат. Я реализовал это, используя Форма, как в ссылке. Проект основан на это стартовое приложение.
Код:
@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.
Как получить фактический вывод базы данных, не зная заранее, сколько столбцов будет в таблице или типы столбцов?
@prasad_ - rs.toString () возвращает адрес в памяти ResultSet в виде строки. Я не этого хочу. Мне нужно фактическое содержимое базы данных.
Внимательно изучите этот документ. Это набор результатов api. У него есть методы для получения информации из вывода запроса: Набор результатов.
вам нужно объединить каждое значение, получив соответствующие столбцы
@ user7294900 Я не знаю количество столбцов в запрашиваемой таблице.
@prasad_ "Интерфейс ResultSet предоставляет методы получения (getBoolean, getLong и т. д.) для получения значений столбца из текущей строки. Значения можно получить, используя либо номер индекса столбца, либо имя столбца." Я не знаю заранее ни типы столбцов, ни количество столбцов.
Вы можете привести пример того, как выглядит строка входного запроса?
@prasad_ Конечно. «ВЫБРАТЬ * ИЗ тиков». Я не знаю всех столбцов в таблице тиков, я просто знаю, что таблица тиков существует. Или как насчет «ВЫБРАТЬ * ИЗ pg_catalog.pg_tables». Это сообщает мне имена таблиц, чтобы я мог запросить их.
В пакете java.sql есть классы, которые помогают вычислить метаданные запрашиваемых таблиц. Примерно так: JDBC - получить имена столбцов. Попробуйте поискать в сети конкретный вопрос, который вы сейчас получаете. Может быть, поискать руководство по JDBC?
@prasad_ Вы упомянули метаданные. Я нашел connection.getMetaData (). Я не знаю, говорит ли это мне количество столбцов в запрашиваемой таблице. Если бы я знал количество столбцов, я мог бы просто сделать rs.getString(columnNumber) для каждого столбца (я не уверен, работает ли rs.getString с столбцами, отличными от String, например, с целыми числами, датами и т. д.).
Может пытается помочь. Можно попробовать одну колонку и посмотреть, как она работает.




Я бы посоветовал для начала упростить ваш код, используя 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";
}
}
См. Также Как получить количество столбцов из набора результатов JDBC? о том, как получить количество столбцов.
Я думаю, вы имеете в виду queryContent, а не queryContext.
Как указано, набрал его как ответ, не проверяя его.
Что делает
rs.toString()?