Как правильно построить иерархию классов в Java?

Пишу прогу, которая импортирует ексель файл в базу данных, все работает отлично, но хотелось бы узнать как можно правильнее организовать иерархию. Использую JDBC драйвер. У меня сейчас она такая:

  1. Main
  2. DatabaseConnection (класс создаёт соединение с базой и загружает в память драйвер)
  3. Handler (производит непосредственно загрузку)
  4. Configs (конфигурация для работы (database name, password, user, driverURI и тд))

Заранее спасибо!


Ответы (1 шт):

Автор решения: Дмитрий

Попробовал сделать рефакторинг, поскольку у вас нет тестов, возможно где-то ошибся. Пожалуйста, задавайте ваши вопросы.

    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    import java.util.stream.Collectors;
    
    public class Main {
    
        public static void main(String[] args) {
            
            Directory directory = new Directory("путь к директории");
            
            List<String> defunctFiles = new ArrayList<>();   
            
            print("Uploading...");
    
            // Индикатор загрузки
            ProgressBar progressBar = new ProgressBar();
            
            Handler handler = new Handler();
    
            // Считает время работы программы  
            long start = System.nanoTime();
    
            for (int i = 0; i < directory.getNumberOfFiles(); i++) {
                try {
                    handler.uploadFile(directory.getDirectoryFile(i));
                } catch (RuntimeException e) {
                    defunctFiles.add(directory.getDirectoryFile(i).getName() + "(" + e.getMessage() + ")");
                }
                progressBar.step(i, directory.getNumberOfFiles() - 1);
            }
            long leadTime = TimeUnit.SECONDS.convert((System.nanoTime() - start), TimeUnit.NANOSECONDS);
            
            print("Uploaded files: " + (directory.getNumberOfFiles()-defunctFiles.size()) + "\\" + directory.getNumberOfFiles());
    
            showDefunctFiles(defunctFiles);
            
            print("Time: " + leadTime + " sec");
        }
    
        /**
         * Функция создания вывода деффектных файлов
         */
        private static void showDefunctFiles(Collection <String> files) {
            if (!files.isEmpty()) print("Defunct files: ", files.stream().collect(Collectors.joining(", ")));
        }
        
        public static void print(Object ... args) {
            for (Object arg : args) System.out.println(arg);
        }
    
    }
    import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;

public class Handler {

    /**
     * Функция загрузки файлов Excel в базу данных
     *
     * @param file - файл, который нужно загрузить
     */
    public void uploadFile(final File file) {

        String sheetName = "название таблицы";

        try (DatabaseConnection connection = new DatabaseConnection()) {
            try (XSSFWorkbook workbook = new XSSFWorkbook(file)) {
                //Класс представляет возможность перебрать все элементы в коллекции без вникания во внутреннюю структуру и устройство коллекций.
                Iterator <Row> rowIterator = getIterator(workbook.getSheet(sheetName));
                while (rowIterator.hasNext()) {
                    Iterator<Cell> cellIterator = getIterator(rowIterator.next());
                    while (cellIterator.hasNext()) {
                        //Ячейки электронной таблицы используются для размещения информации.
                        Cell cell = cellIterator.next();
                        //Проверка типа информации, которая содержиться в даной ячейке, запись значений в базу даных
                        if (CellType.NUMERIC.equals(cell.getCellType())) {
                            connection.set(cell.getColumnIndex(),cell.getNumericCellValue());
                        } else if (CellType.STRING.equals(cell.getCellType())) {
                            String cellValue = cell.getStringCellValue().trim();
                            if (!cellValue.isEmpty()) connection.set(cell.getColumnIndex(), cellValue);
                        }
                    }
                    connection.set(11, file.getName()).update();
                }
            } catch (IOException | InvalidFormatException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private <T> Iterator<T> getIterator(Iterable<T> iterable) {
        Iterator<T> iterator = iterable.iterator();
        if (iterator.hasNext()) iterator.next();
        return iterator;
    }

}
    
    import java.io.Closeable;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    
    public class DatabaseConnection implements Closeable {
    
        private static final String HOST = "";
        private static final String PORT = "";
        private static final String USERNAME = "";
        private static final String PASSWORD = "";
        private static final String DB_NAME = "";
        private static final String DB_DRIVER_NAME = "oracle.jdbc.driver.OracleDriver";
        private static final String SQL = "insert into \"название таблицы\"(\"названия колонок\") values (?,?,?,?,?,?,?,?,?,?,?)";
    
        private static final Connection CONNECTION;
    
        private final PreparedStatement preparedStatement;
    
        static {
            try {
                Class.forName(DB_DRIVER_NAME);
                CONNECTION = DriverManager.getConnection("jdbc:oracle:thin:@" + HOST + ":" + PORT + "/" + DB_NAME, USERNAME, PASSWORD);
            } catch (ClassNotFoundException | SQLException ex) {
                throw new RuntimeException(ex);
            }
        }
    
        public DatabaseConnection() {
            try {
                //Для подтверждения SQL-запросов мы используем объекты, созданные с использованием этого интерфейса.
                this.preparedStatement = CONNECTION.prepareStatement(SQL);
            } catch (SQLException ex) {
                throw new RuntimeException(ex);
            }
        }
    
        public DatabaseConnection update() {
            try {
                preparedStatement.executeUpdate();
                return this;
            } catch (SQLException ex) {
                throw new RuntimeException(ex);
            }
        }
    
        public DatabaseConnection set(int parameterIndex, double x) {
            try {
                preparedStatement.setDouble(parameterIndex, x);
                return this;
            } catch (SQLException ex) {
                throw new RuntimeException(ex);
            }
        }
        
        public DatabaseConnection set(int parameterIndex, String x) {
            try {
                preparedStatement.setString(parameterIndex, x);
                return this;
            } catch (SQLException ex) {
                throw new RuntimeException(ex);
            }
        }
    
        @Override
        public void close() {
            try {
                preparedStatement.close();
            } catch (SQLException ex) {
                throw new RuntimeException(ex);
            }
        }
    
    }
→ Ссылка