Java Spring Boot postgresql с HikariCP - получить необработанный строковый вывод из запроса оператора

Я пытаюсь написать 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);
    }
  }
}

Форма выглядит так:

Java Spring Boot postgresql с HikariCP - получить необработанный строковый вывод из запроса оператора


Но результат, который я получаю, выглядит так:

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.

Как получить фактический вывод базы данных, не зная заранее, сколько столбцов будет в таблице или типы столбцов?

Что делает rs.toString()?

prasad_ 17.09.2018 07:41

@prasad_ - rs.toString () возвращает адрес в памяти ResultSet в виде строки. Я не этого хочу. Мне нужно фактическое содержимое базы данных.

Michael Lafayette 17.09.2018 07:42

Внимательно изучите этот документ. Это набор результатов api. У него есть методы для получения информации из вывода запроса: Набор результатов.

prasad_ 17.09.2018 07:45

вам нужно объединить каждое значение, получив соответствующие столбцы

user7294900 17.09.2018 07:46

@ user7294900 Я не знаю количество столбцов в запрашиваемой таблице.

Michael Lafayette 17.09.2018 07:48

@prasad_ "Интерфейс ResultSet предоставляет методы получения (getBoolean, getLong и т. д.) для получения значений столбца из текущей строки. Значения можно получить, используя либо номер индекса столбца, либо имя столбца." Я не знаю заранее ни типы столбцов, ни количество столбцов.

Michael Lafayette 17.09.2018 07:49

Вы можете привести пример того, как выглядит строка входного запроса?

prasad_ 17.09.2018 07:50

@prasad_ Конечно. «ВЫБРАТЬ * ИЗ тиков». Я не знаю всех столбцов в таблице тиков, я просто знаю, что таблица тиков существует. Или как насчет «ВЫБРАТЬ * ИЗ pg_catalog.pg_tables». Это сообщает мне имена таблиц, чтобы я мог запросить их.

Michael Lafayette 17.09.2018 07:52

В пакете java.sql есть классы, которые помогают вычислить метаданные запрашиваемых таблиц. Примерно так: JDBC - получить имена столбцов. Попробуйте поискать в сети конкретный вопрос, который вы сейчас получаете. Может быть, поискать руководство по JDBC?

prasad_ 17.09.2018 07:55

@prasad_ Вы упомянули метаданные. Я нашел connection.getMetaData (). Я не знаю, говорит ли это мне количество столбцов в запрашиваемой таблице. Если бы я знал количество столбцов, я мог бы просто сделать rs.getString(columnNumber) для каждого столбца (я не уверен, работает ли rs.getString с столбцами, отличными от String, например, с целыми числами, датами и т. д.).

Michael Lafayette 17.09.2018 08:03

Может пытается помочь. Можно попробовать одну колонку и посмотреть, как она работает.

prasad_ 17.09.2018 08:04
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
11
955
1

Ответы 1

Я бы посоветовал для начала упростить ваш код, используя 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.

Michael Lafayette 17.09.2018 08:08

Как указано, набрал его как ответ, не проверяя его.

M. Deinum 17.09.2018 08:09

Другие вопросы по теме