Как я могу решить огромные проблемы с производительностью при сравнении и обновлении данных с помощью Java? - PullRequest
0 голосов
/ 04 декабря 2018

Я хочу сравнить два списка с объектами одного типа, которые имеют около 30 значений.Когда есть различия, новое значение должно быть обновлено в базе данных.
Часть, где мой код становится действительно очень медленным, например, одно обновление каждую минуту, - это когда данные должны обновляться.

чтение всехнаборы данных из БД и Excel быстро.Но когда дело доходит до приведенного ниже кода, он уже начинает почти останавливаться после 200 наборов данных.

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

Может быть, каким-то образом создается много объектов или что-то в этом роде?

РЕДАКТИРОВАТЬ: я запускаю программу с IntelliJ.Когда я закрываю работающее приложение и запускаю его снова, оно загружает уже медленно загруженные наборы данных из предыдущего раза очень быстро, но затем снова замедляется.Может, что-то с кешем не так?

Вот мой код:

public class MainWindow_Controller {

List<Pensioner> pensionerDB = new ArrayList();
List<Pensioner> pensionerExcel = new ArrayList();

Boolean checkStatusChange = false;
String pathDB = "";

@FXML
private TextField tfDBPath;

/**
 * This method compares the pensioners from database with the ones from the excel head file.
 * Based on matching pensionInsuranceNumbers the method checks if the status is different.
 * If it is different, the status gets updated.
 *
 * @param event
 */
@FXML
void getStatusChange(ActionEvent event) throws FileNotFoundException, IllegalAccessException, SQLException {
    String type = "Statuswechsel";
    if (pensionerDB.isEmpty() || pensionerExcel.isEmpty()) {
        getLists();
    }

    pathDB = tfDBPath.getText();
    //load pensioners from database in first list
    pensionerDB = array[0];

    //load pensioners from excel head file in second list
    pensionerExcel = array[1];

    //compare pensionInsuranceNumber from first list with pensionInsuranceNumber from second list and move missing datasets to third list
    List<Pensioner> result = new ArrayList();

    Database.connect(pathDB);

    //iterates over the two lists with pensioners in database and pensioners in excel files and adds the dataset with matching pensionInsuranceNumbers into the result list.
    for (int i = 0; i < pensionerExcel.size(); i++) {
        System.out.println("Processing Excelrow Number: " + i);
        for (int j = 0; j < pensionerDB.size(); j++) {
            updatePensionerData(pensionerExcel, pensionerDB, pathDB, i, j);
            if (pensionerExcel.get(i).getPensionInsuranceNumber() == pensionerDB.get(j).getPensionInsuranceNumber() && pensionerExcel.get(i).getStatusOld() != pensionerDB.get(j).getStatusOld()) {
                checkStatusChange = true;
                pensionerDB.get(j).setStatusNew(pensionerDB.get(j).getStatusOld());
                pensionerDB.get(j).setStatusOld(pensionerExcel.get(i).getStatusOld());
                result.add(pensionerDB.get(j));
                break;
            } else if (pensionerExcel.get(i).getPensionInsuranceNumber() == pensionerDB.get(j).getPensionInsuranceNumber() && pensionerExcel.get(i).getStatusOld() == pensionerDB.get(j).getStatusOld()) {
                break;
            }
        }
    }
    Database.close();

}

public void updatePensionerData(List<Pensioner> pensionerExcel, List<Pensioner> pensionerDB, String pathDB, int i, int j) {
    if (pensionerExcel.get(i).getPensionInsuranceNumber() == pensionerDB.get(j).getPensionInsuranceNumber()) {
        if (pensionerExcel.get(i).getIdkz() != pensionerDB.get(j).getIdkz()) {
            Database.updateIdkz(pensionerExcel.get(i), pathDB);
        }
        if (!pensionerExcel.get(i).getCompany().equals(pensionerDB.get(j).getCompany())) {
            Database.updateCompany(pensionerExcel.get(i), pathDB);
        }
        if (pensionerExcel.get(i).getPersonelId() != pensionerDB.get(j).getPersonelId()) {
            Database.updatePersonelId(pensionerExcel.get(i), pathDB);
        }

        if (!pensionerExcel.get(i).getBirthDate().isEqual(pensionerDB.get(j).getBirthDate())) {
            Database.updateBirthDate(pensionerExcel.get(i), pathDB);
        }
        //...
        //26 more if statements for the other values
        //...
    }
}

}

Методы моей базы данных:

public static void updateIdkz(Pensioner p, String pathDB) {
    String update = String.format("UPDATE Pensionär SET idkz = ?");
    try {
        ps = connection.prepareStatement(update);
        ps.setInt(1, p.getIdkz());
        ps.executeUpdate();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static void updatePersonelId(Pensioner p, String pathDB) {
    String update = String.format("UPDATE Pensionär SET PersNr = ? Where pknr = ?");
    try {
        ps = connection.prepareStatement(update);
        ps.setInt(1, p.getPersonelId());
        ps.setInt(2, p.getPensionInsuranceNumber());
        ps.executeUpdate();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static void updateBirthDate(Pensioner p, String pathDB) {
    String update = String.format("UPDATE Pensionär SET Geburtsdatum = ? Where pknr = ?");
    try {
        ps = connection.prepareStatement(update);
        ps.setDate(1, Date.valueOf(p.getBirthDate()));
        ps.setInt(2, p.getPensionInsuranceNumber());
        ps.executeUpdate();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Спасибоза вашу помощь

Ответы [ 2 ]

0 голосов
/ 04 декабря 2018

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

class Test implements Closeable {

    // reusable PreparedStatements
    private final PreparedStatement updateIdkz;
    private final PreparedStatement updatePersonelId;
    private final PreparedStatement updateBirthDate;

    public Test(Connection con) throws SQLException {
        this.updateIdkz = con
            .prepareStatement("UPDATE Pensionär SET idkz = ?");
        this.updatePersonelId = con
            .prepareStatement("UPDATE Pensionär SET PersNr = ? Where pknr = ?");
        this.updateBirthDate = con
            .prepareStatement("UPDATE Pensionär SET Geburtsdatum = ? Where pknr = ?");
    }

    /** Closes all the prepared statements. */
    @Override
    public void close() throws IOException {
        try {
            updateIdkz.close();
        } catch (SQLException e) {
        }
        try {
            updatePersonelId.close();
        } catch (SQLException e) {
        }
        try {
            updateBirthDate.close();
        } catch (SQLException e) {
        }
    }

    public void addBatchUpdateIdkz(Pensioner p) {
        try {
            updateIdkz.clearParameters();
            updateIdkz.setInt(1, p.getIdkz());
            updateIdkz.addBatch();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void addBatchUpdatePersonelId(Pensioner p) {
        try {
            updatePersonelId.clearParameters();
            updatePersonelId.setInt(1, p.getPersonelId());
            updatePersonelId.setInt(2, p.getPensionInsuranceNumber());
            updatePersonelId.addBatch();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void addBatchUpdateBirthDate(Pensioner p) {
        try {
            updateBirthDate.clearParameters();
            updateBirthDate.setDate(1, Date.valueOf(p.getBirthDate()));
            updateBirthDate.setInt(2, p.getPensionInsuranceNumber());
            updateBirthDate.addBatch();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void executeBatchUpdateIdkz() throws SQLException {
        updateIdkz.executeBatch();
    }

    public void executeBatchUpdatePersonelId() throws SQLException {
        updatePersonelId.executeBatch();
    }

    public void executeBatchUpdateBirthDate() throws SQLException {
        updateBirthDate.executeBatch();
    }

    public static void main(String[] args) {

        Pensioner p1 = null, p2 = null, p3 = null, p4 = null;
        Connection con = null;

        // try with resources to ensure you close the prepared statements
        try (Test t = new Test(con);) {
            // Update multiple Idkz
            t.addBatchUpdateIdkz(p1);
            t.addBatchUpdateIdkz(p2);
            t.addBatchUpdateIdkz(p3);
            t.addBatchUpdateIdkz(p4);
            t.executeBatchUpdateIdkz();

            // Update multile PersonelId
            t.addBatchUpdatePersonelId(p1);
            t.addBatchUpdatePersonelId(p2);
            t.addBatchUpdatePersonelId(p3);
            t.addBatchUpdatePersonelId(p4);
            t.executeBatchUpdatePersonelId();

            // etc...
        } catch (IOException e) {
            e.printStackTrace();
        } catch (SQLException e1) {
            e1.printStackTrace();
        }
    }
}
0 голосов
/ 04 декабря 2018

Вы можете добавить блок finally для каждого try... catch и закрыть объект PreparedStatement.

Пример:

public static void updateIdkz(Pensioner p, String pathDB) {
  String update = String.format("UPDATE Pensionär SET idkz = ?");
  try {
      ps = connection.prepareStatement(update);
      ps.setInt(1, p.getIdkz());
      ps.executeUpdate();
  } catch (Exception e) {
      e.printStackTrace();
  }
  finally {
    ps.close();
  }

Дайте мне знать, если он работает.

...