Как переписать код в стиле ООП?

94
19 июня 2021, 01:00

Всем привет! Объясните пожалуйста, как переписать данный код в стиле ООП (если возможно то с использованием интерфейсов). Собственно код:

public class ReadCSVWriteToDB {
    @SuppressWarnings("resource")
    public static void main(String[] args) throws Exception {
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/ebookshop?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC",
                "myuser", "1234");
        Statement stmt = conn.createStatement();

        CSVReader reader = new CSVReader(new FileReader("teachers.csv"), ',', '"');
        //каждый элемент листа - строка, каждый элемент String[] - значение в столбце
        List<String[]> lines = reader.readAll();

        CSVReader reader2 = new CSVReader(new FileReader("subjects.csv"), ',', '"');
        List<String[]> lines2 = reader2.readAll();

        CSVReader reader3 = new CSVReader(new FileReader("classes.csv"), ',', '"');
        List<String[]> lines3 = reader3.readAll();
        CSVReader reader4 = new CSVReader(new FileReader("teaches.csv"), ',', '"');
        List<String[]> lines4 = reader4.readAll();
        CSVReader reader5 = new CSVReader(new FileReader("students.csv"), ',', '"');
        List<String[]> lines5 = reader5.readAll();
        CSVReader reader6 = new CSVReader(new FileReader("raitings.csv"), ',', '"');
        List<String[]> lines6 = reader6.readAll();
        try {

            String teachersTable = "create table if not exists teachers("
                    + "id_t int not null, "
                    + "ФИО varchar(50), "
                    + "Руководство varchar(50) not null, "
                    + "primary key(id_t)"
                    + ")";
            String subjectsTable = "create table if not exists subjects("
                    + "id_sbj int not null, "
                    + "Название varchar(50), "
                    + "primary key(id_sbj)"
                    + ")";
            String classesTable = "create table if not exists classes("
                    + "Название varchar(50) not null, "
                    + "id_t int not null, "
                    + "foreign key(id_t) references teachers(id_t) on delete cascade, "
                    + "primary key(Название)"
                    + ")";
            String teachesTable = "create table if not exists teaches("
                    + "id_t int not null, "
                    + "id_sbj int not null, "
                    + "Название varchar(50) not null, "
                    + "foreign key (Название) references classes (Название),"
                    + "foreign key(id_t) references teachers(id_t) on delete cascade,"
                    + "foreign key(id_sbj) references subjects(id_sbj),"
                    + "primary key(id_t, id_sbj)"
                    + ")";
            String studentsTable = "create table if not exists students("
                    + "id_std int not null, "
                    + "ФИО varchar(50), "
                    + "Класс varchar(50), "
                    + "foreign key(Класс) references classes(Название), "
                    + "primary key(id_std)"
                    + ")";
            String raitingsTable = "create table if not exists raitings("
                    + "id_std int not null, "
                    + "id_sbj int not null, "
                    + "Оценка int not null, "
                    + "key(id_std),"
                    + "key(id_sbj), "
                    + "foreign key(id_std) references students(id_std) on delete cascade, "
                    + "foreign key(id_sbj) references subjects(id_sbj) on delete cascade, "
                    + "primary key(id_std, id_sbj)"
                    + ")";
            //String query = "show tables";
            stmt.execute(teachersTable);
            stmt.execute(subjectsTable);
            stmt.execute(classesTable);
            stmt.execute(teachesTable);
            stmt.execute(studentsTable);
            stmt.execute(raitingsTable);
            if(lines!=null) {
                stmt.executeUpdate("delete from raitings");
                stmt.executeUpdate("delete from students");
                stmt.executeUpdate("delete from teaches");
                stmt.executeUpdate("delete from subjects");
                stmt.executeUpdate("delete from classes");
                stmt.executeUpdate("delete from teachers");
                for (int index = 0; index < lines.size(); ++index) {
                    String[] line = lines.get(index);
                    String sqlInsert = String.format("insert into teachers values ('%s', '%s', '%s')", line[0], line[1], line[2]);
                    int countInserted = stmt.executeUpdate(sqlInsert);

                }
            }
            if (lines2!=null) {
                stmt.executeUpdate("delete from raitings");
                stmt.executeUpdate("delete from students");
                stmt.executeUpdate("delete from teaches");
                stmt.executeUpdate("delete from subjects");
                stmt.executeUpdate("delete from classes");
                for (int index2 = 0; index2 < lines2.size(); ++index2) {
                    String[] line2 = lines2.get(index2);
                    String sqlInsert2 = String.format("insert into subjects values ('%s', '%s')", line2[0], line2[1]);
                    int countInserted2 = stmt.executeUpdate(sqlInsert2);
                }
            }

            if (lines3!=null) {
                stmt.executeUpdate("delete from raitings");
                stmt.executeUpdate("delete from students");
                stmt.executeUpdate("delete from teaches");
                stmt.executeUpdate("delete from classes");
                for (int index3 = 0; index3 < lines3.size(); ++index3) {
                    String[] line3 = lines3.get(index3);
                    String sqlInsert3 = String.format("insert into classes values ('%s', '%s')", line3[0], line3[1]);
                    int countInserted2 = stmt.executeUpdate(sqlInsert3);
                }
            }

            if (lines4!=null) {
                stmt.executeUpdate("delete from raitings");
                stmt.executeUpdate("delete from students");
                stmt.executeUpdate("delete from teaches");
                for (int index4 = 0; index4 < lines4.size(); ++index4) {
                    String[] line4 = lines4.get(index4);
                    String sqlInsert4 = String.format("insert into teaches values ('%s', '%s', '%s')", line4[0], line4[1], line4[2]);
                    int countInserted2 = stmt.executeUpdate(sqlInsert4);
                }
            }
            if (lines5!=null) {
                stmt.executeUpdate("delete from raitings");
                stmt.executeUpdate("delete from students");
                for (int index5 = 0; index5 < lines5.size(); ++index5) {
                    String[] line5 = lines5.get(index5);
                    String sqlInsert5 = String.format("insert into students values ('%s', '%s', '%s')", line5[0], line5[1], line5[2]);
                    int countInserted2 = stmt.executeUpdate(sqlInsert5);
                }
            }

            if (lines6!=null) {
                stmt.executeUpdate("delete from raitings");
                for (int index6 = 0; index6 < lines6.size(); ++index6) {

                    String[] line6 = lines6.get(index6);
                    String sqlInsert6 = String.format("insert into raitings values ('%s', '%s', '%s')", line6[0], line6[1], line6[2]);
                    int countInserted2 = stmt.executeUpdate(sqlInsert6);
                }
            }
            //Ввод SQL запроса в консоль
            System.out.println("Результат запроса смотрите в файле result");
            System.out.println("Введите запрос: ");
            InputStream inputStream = System.in;
            Reader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String sqlres = bufferedReader.readLine();
            //Вывод результата запроса в файл
            CSVWriter writer = new CSVWriter(new FileWriter("result.csv"), '\t');
            Boolean includeHeaders = true;
            ResultSet resultSet = stmt.executeQuery(sqlres);
            writer.writeAll(resultSet, includeHeaders);
            writer.close();

        } catch (SQLException ex) {
            ex.printStackTrace();
        }

    }
}

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

Answer 1

Например можно как-то так.

  1. Создать класс, который будет давать подключение к БД. Он будет реализовывать интерфейс описывающий методы для работы с БД. Например для открытия подключения, создания таблицы, запроса в неё, вставки данных. Это нужно для возможности потом заменить БД на другую. В таком случае надо будет только один класс переписать.
  2. Создать класс, который будет читать и писать данные из CSV. Он также и по тем же причинам должен реализовывать интерфейс.
  3. Собственно основной класс, который будет иметь доступ к вышеозначенным классам. Он будет заниматься приёмом ввода от юзера и вывода ему инфы. В принципе, так же тут можно выделить интерфейс ввода-вывода, чтобы потом консоль можно было заменить на UI.
Answer 2

Ну во-первых надо понимать что первый и очень важный принцип ООП - инкапсуляция. Вся работа с данными должна быть внутри объекта, никто за пределами объекта не должен знать как объект работает со своими данными. Объект должен следовать контракту (интерфейсу), который реализует, остальному доступа быть не должно.

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

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

import ...
public interface SimpleTable extends Iterable<String[]> {
  public void add(final String[] data);
  public void truncate();
}
public final class CSVTable implements SimpleTable {
  private final CSVReader reader;
  private final String file;
  public CSVTable(final String file) {
    this.reader = new CSVReader(new FileReader(file), ',', '"');
    this.file = file;
  }
  @Override
  public Iterator<String[]> iterator() {
    return this.reader.iterator();
  }
  /** @todo реализовать запись в файл */
  @Override
  public void add(final String[] data) {
    throw new UnsupportedOperationException();
  }
  /** @todo реализовать очистку файла */
  @Override
  public void truncate() {
    throw new UnsupportedOperationException();
  }
  public void add(final ResultSet data) {
    CSVWriter writer = new CSVWriter(new FileWriterthis.(file), '\t');
    writer.writeAll(data, true);
    writer.close();
  }
}
public final class MySQLTable implements SimpleTable {
  private final Connection db;
  private final String name;
  public MySQLTable(final Connection db, final String n) {
    this.db = db;
    this.name = n;
  }
  public MySQLTable(final Connection db, final String n,
    final String script) {
    this(db, n)
    try {Statement s = this.db.createStatement()) {
      s.execute(script);
    }
  }
  /** @todo чтение из таблицы select * from name */
  @Override
  public Iterator<String[]> iterator() {
    throw new UnsupportedOperationException();
  }
  @Override
  public void add(final String[] data) {
    StringBuilder query = new StringBuilder();
    query.append("insert into ").append(this.name).append(" values (");
    boolean first = true;
    for (String val: data) {
      if (first)
        first = false;
      else
        query.append(",");
      query.append("'").append(val).append("'");
    }
    try {Statement s = this.db.createStatement()) {
      s.executeUpdate(query.append(")").toString());
    }
  }
  @Override
  public void truncate() {
    try {Statement s = this.db.createStatement()) {
      s.executeUpdate("delete from " + this.name);
    }
  }
}
public class App {
  private Connection db;
  public App(final Connection db) {
    this.db = db;
  }
  private void transfer(final SimpleTable src, final SimpleTable dst) {
    dst.truncate();
    for (String[] data: src)
      dst.add(data);
  }
  public static void main(String[] args) throws Exception {
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/ebookshop?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC",
      "myuser", "1234");
    App app = new App(conn);
    app.transfer(
      new CSVTable("teachers.csv"),
      new MySQLTable(
        conn, "teachers",
        String.join(
          "", 
          "create table if not exists teachers(",
          "id_t int not null, ",
          "ФИО varchar(50), ",
          "Руководство varchar(50) not null, ",
          "primary key(id_t)",
          ")"
        )
      )
    );
    app.transfer(
      new CSVTable("subjects.csv"),
      new MySQLTable(
        conn, "subjects",
        String.join(
          "", 
          "create table if not exists subjects(",
          "id_sbj int not null, ",
          "Название varchar(50), ",
          "primary key(id_sbj)",
          ")"
        )
      )
    );
    // @todo все другие таблицы аналогично
    // ...
    System.out.println("Результат запроса смотрите в файле result");
    System.out.println("Введите запрос: ");
    new CSVTable("result.csv").add(conn.createStatement().executeQuery(
      new BufferedReader(new InputStreamReader(System.in)).readLine()
    ));
  }
}

Все равно объекты получились довольно абстрактные, XXXTable. Дальнейшие улучшения - создание объектов Teachers, Subjects которые будут инкапсулировать формат таблицы в БД

READ ALSO
Как найти строку или слова в StringBuilder

Как найти строку или слова в StringBuilder

Как найти слово или строку для того чтобы занести её в HashMap в ключ например:

92
Подключение OpenCV к проекту Java

Подключение OpenCV к проекту Java

При выполнении кода из туториала:

101
Ошибка: java: not a statement

Ошибка: java: not a statement

На выводе получаю ошибку:

110