Не удается разобрать файл с помощью JDBC - PullRequest
0 голосов
/ 20 марта 2020

Я пытаюсь проанализировать файл с разделителями канала и вставить поля в таблицу. Когда я запускаю приложение, в моей БД ничего не происходит. Моя БД имеет 4 столбца (имя_счета, имя_команды и имя_системы, CreateDt). Файл, который я анализирую, имеет дату в первой строке, а затем дополнительные данные. Строки, следующие за мной, нужны только первые 3 поля в каждом, остальные - дополнительные данные. последняя строка - это количество строк. я пропустил дату вставки, потому что пока, но хочу вернуться к ней после того, как хотя бы смог вставить первые 3 поля. У меня мало опыта разбора файла и хранения данных в БД, и я просмотрел примеры jdb c, чтобы добраться до этой точки, но я борюсь и уверен, что есть лучший способ.

Пример файла

20200310|extra|extra|extra||
Mn1223|01192|windows|extra|extra|extra||
Sd1223|02390|linux|extra|extra|extra||
2

формат таблицы

account_name      command_name   system_name    createDt
Mn1223            01192          windows        20200310
Sd1223            02390          linux          20200310

Код для анализа и вставки в БД

public List insertZygateData (List<ZygateEntity> parseData) throws Exception {
        String filePath = "C:\\DEV\\Test_file.xlsx";


        List<String> lines = Files.readAllLines(Paths.get(filePath));

        // remove date and amount
        lines.remove(0);
        lines.remove(lines.size() - 1);

        for (ZygateEntity zygateInfo : parseData){
                    new MapSqlParameterSource("account_name", zygateInfo.getAccountName())
                            .addValue("command_name", zygateInfo.getCommandName())
                            .addValue("system_name", zygateInfo.getSystemName())
                            .getValues();

        }
        return lines.stream()
                .map(s -> s.split("[|]")).map(val -> new ZygateEntity(val[0],val[1],val[2])).collect(Collectors.toList());


    }


    public boolean cleantheTable() throws SQLException {

        String sql = "INSERT INTO Landing.midrange_xygate_load (account_name,command_name,system_name)"+
                "VALUES (:account_name,:command_name,:system_name)";

        boolean truncated = false;
        Statement stmt = null;
        try {
            String sqlTruncate = "truncate table Landing.midrange_xygate_load";
            jdbcTemplate.execute(sqlTruncate);
            truncated = true;

        } catch (Exception e) {
            e.printStackTrace();
            truncated = false;
            return truncated;
        } finally {
            if (stmt != null) {
                jdbcTemplate.execute(sql);
                stmt.close();
            }

        }
        log.info("Clean the table return value :" + truncated);
        return truncated;
    }
}

Объект / Модель

public ZygateEntity(String accountName, String commandName, String systemName){
        this.accountName=accountName;
        this.commandName=commandName;
        this.systemName=systemName;
    }

   //getters and setters
    @Override
    public String toString() {
        return "ZygateEntity [accountName=" + accountName + ", commandName=" + commandName + ", systemName=" + systemName + ", createDt=" + createDt +"]";
    }
}

1 Ответ

2 голосов
/ 21 марта 2020

Взглянув на то, что вы предоставили, кажется, что у вас есть беспорядочная коллекция битов кода, и хотя большая часть этого есть, она не все там и не совсем все в правильном порядке.

Чтобы получить некоторую ясность, попробуйте разбить то, что вы делаете, на отдельные этапы, и найдите метод, который фокусируется на каждом этапе. В частности, вы пишете

Я пытаюсь проанализировать файл с разделителями каналов и вставить поля в таблицу

Это естественно разбивается на две части:

  • синтаксический анализ файла с разделителями каналов и
  • вставка полей в таблицу.

В первой части, похоже, большинство частей уже есть в вашем insertZygateData метод. В частности, эта строка считывает все строки файла в список:

    List<String> lines = Files.readAllLines(Paths.get(filePath));

Затем эти строки удаляют первую и последнюю строки из списка прочитанных строк:

    // remove date and amount
    lines.remove(0);
    lines.remove(lines.size() - 1);

Затем у вас есть некоторый код, который выглядит немного неуместным: похоже, это связано с вставкой в ​​базу данных, но мы еще не создали наш список ZygateEntity объектов, так как мы еще не закончили чтение файла. Давайте пока поместим это for l oop в одну сторону.

Наконец, мы берем список строк, которые мы читаем, разбиваем их по каналам, создаем ZygateEntity объекты из деталей и создаем List из этих объектов, которые мы затем возвращаем.

    return lines.stream()
            .map(s -> s.split("[|]")).map(val -> new ZygateEntity(val[0],val[1],val[2])).collect(Collectors.toList());

Соединяя этот лот, у нас есть полезный метод, который анализирует файл, выполняя первую часть задачи:

    private List<ZygateEntity> parseZygateData() throws IOException {
        String filePath = "C:\\DEV\\Test_file.xlsx";

        List<String> lines = Files.readAllLines(Paths.get(filePath));

        // remove date and amount
        lines.remove(0);
        lines.remove(lines.size() - 1);

        return lines.stream()
                .map(s -> s.split("[|]")).map(val -> new ZygateEntity(val[0],val[1],val[2])).collect(Collectors.toList());
    }

(Конечно, мы могли бы добавить параметр для пути к файлу для чтения, но для того, чтобы что-то работало, нормально придерживаться текущего жестко заданного пути к файлу.)


* 1038 Итак, у нас есть список из ZygateEntity объектов. Как мы напишем метод для вставки их в базу данных?

Мы можем найти пару необходимых нам компонентов в вашем примере кода. Во-первых, нам нужен оператор SQL для вставки данных. Это в вашем cleanThetable методе:

    String sql = "INSERT INTO Landing.midrange_xygate_load (account_name,command_name,system_name)"+
            "VALUES (:account_name,:command_name,:system_name)";

У нас тогда есть l oop:

    for (ZygateEntity zygateInfo : parseData){
                new MapSqlParameterSource("account_name", zygateInfo.getAccountName())
                        .addValue("command_name", zygateInfo.getCommandName())
                        .addValue("system_name", zygateInfo.getSystemName())
                        .getValues();
    }

Этот l oop создает MapSqlParameterSource из каждого ZygateEntity объекта, а затем преобразует его в Map<String, Object>, вызывая метод getValues(). Но тогда это ничего не делает с этим значением. Фактически вы создаете эти объекты и снова избавляетесь от них, ничего не делая с ними. Это не идеально.

A MapSqlParameterSource используется с пружиной NamedParameterJdbcTemplate. В вашем коде упоминается jdbcTemplate, представляющее собой поле в классе, которое анализирует данные и вставляет их в базу данных, но вы не показываете полный код этого класса. Я собираюсь предположить, что это NamedParameterJdbcTemplate, а не "обычный" JdbcTemplate.

NamedParameterJdbcTemplate содержит метод update, который принимает строку SQL и SqlParameterSource. У нас есть строка SQL, и мы создаем объекты MapSqlParameterSource, поэтому мы можем использовать их для выполнения вставки. Нет смысла создавать один из этих MapSqlParameterSource объектов только для преобразования его в карту, поэтому давайте удалим вызов getValues().

Итак, теперь у нас есть метод для вставки данных в базу данных:

public void insertZygateData(List<ZygateEntity> parseData) {
    String sql = "INSERT INTO Landing.midrange_xygate_load (account_name,command_name,system_name)"+
            "VALUES (:account_name,:command_name,:system_name)";

    for (ZygateEntity zygateInfo : parseData){
        SqlParameterSource source = new MapSqlParameterSource("account_name", zygateInfo.getAccountName())
                .addValue("command_name", zygateInfo.getCommandName())
                .addValue("system_name", zygateInfo.getSystemName());
        jdbcTemplate.update(sql, source);
    }
}

Наконец, давайте посмотрим на ваш cleanThetable метод. Как и в случае с другими, давайте сосредоточимся на одной задаче: похоже, что в тот момент, когда вы пытаетесь удалить данные из таблицы, а затем вставить их тем же методом, давайте просто сосредоточимся на удалении данных. теперь у нас есть метод для вставки данных.

Мы не можем сразу избавиться от строки String sql = ..., потому что блок finally в вашем коде использует ее. Если stmt не равно нулю, вы пытаетесь запустить оператор INSERT и затем закрыть stmt.

Однако stmt никогда не присваивается никакое значение, кроме null, поэтому оно остается null. Поэтому stmt != null всегда false, поэтому оператор INSERT никогда не выполняется. Ваш finally блок никогда ничего не делает, так что лучше всего его полностью удалить. С отсутствующим блоком finally вы также можете избавиться от локальной переменной stmt и строки sql, и у нас останется метод, целью которого является усечение таблицы:

public boolean cleantheTable() throws SQLException {
    boolean truncated = false;
    try {
        String sqlTruncate = "truncate table Landing.midrange_xygate_load";
        jdbcTemplate.execute(sqlTruncate);
        truncated = true;

    } catch (Exception e) {
        e.printStackTrace();
        truncated = false;
        return truncated;
    }
    log.info("Clean the table return value :" + truncated);
    return truncated;
}

I Вы оставите за собой право написать код, который вызывает эти методы. Я написал некоторый код для этой цели, и он успешно запустился и был вставлен в базу данных.


Итак, в общем, данные не записывались в вашу базу данных, потому что вы никогда не обращались к базе данных вставить любой. В вашем методе insertZygateData вы создавали объекты-источники параметров, но не делали с ними ничего полезного, а в вашем методе cleanThetable выглядело, как будто вы пытались вставить данные, но ваша строка jdbcTemplate.execute(sql), которая пыталась это сделать это никогда не бежало. Даже если stmt не равно нулю, эта строка не будет работать, поскольку вы нигде не передавали значения параметров: вы получите исключение из базы данных, так как оно будет ожидать значений параметров, но вы никогда не дадите его любой.

Надеюсь, мое объяснение даст вам способ заставить ваш код работать и поможет понять, почему это не так.

...