Несколько отношений "один ко многим" в Spring JDBC - программирование
Подтвердить что ты не робот

Несколько отношений "один ко многим" в Spring JDBC

Я использую Spring JDBC, и я немного не уверен в том, как работать с несколькими отношениями один-ко-многим (или многими-ко-многим). В этом случае я вставляю репозиторий в один из моих resultsetextractors, чтобы я мог получить его ассоциации. Это способ сделать это? Это плохо? Есть ли другие способы?

Примечание. Я оставил инъекцию репозитория

public class SomeResultSetExtractor implements ResultSetExtractor {

  public Object extractData(ResultSet rs) throws SQLException, DataAccessException {
    List result = new LinkedList();

    while (rs.next()) {
        SomeObject object = new SomeObject(rs.getString(1), rs.getLong(2));
        result.add(object);

        List<AnotherObject> otherObjects = anotherRepository.findAllById(object.getId);
        object.setOtherObjects(otherObjects);
        // and so on
    }

    return result;

  }
}

Okey, поэтому после прочтения ответа Dmytro Polivenok я изменил интерфейс RowMapper, и в настоящее время я использую другие репозитории для заполнения всех ассоциаций, как показано в моем примере. Это хороший способ сделать это?

4b9b3361

Ответ 1

Я думаю, что хорошей практикой для Spring JDBC и SQL-запросов в общем случае является использование одного запроса для каждого объекта.

например. предположим, что эта модель:

  • Клиент (customerId, имя, возраст,...)
  • Адрес (customerId, тип, улица, город,...)
  • PaymentOption (customerId, cardnumber, cardtype,...)

  • Клиент 1 --- * Адрес

  • Клиент 1 --- * PaymentOption

Я бы построил 3 запроса, 3 Daos, 3 ResultSetExtractors/RowcallbackHandlers:

  • CustomerDao с readCustomerData (Customer или List)
  • AddressDao с readAddressForCustomer (Клиент или Список)
  • PaymentOptionDao с помощью readPaymentOptionsForCustomer (Клиент или Список)

Если вы испекли это в 1 запросе, вам нужно будет построить некоторую логику, чтобы вернуть карточный продукт.

  • т.е. если у клиента есть 3 адреса и 2 варианта оплаты, запрос будет возвращать 6 строк.
  • Это довольно сложно, если адрес или PaymentOption не имеют собственного первичного ключа.

Для многих-многих:

  • Клиент * --рекомендации-- * Продукт

Я бы, вероятно, построил:

  • CustomerDao.readRecommendationsAndProductKeys
  • getDistinctListOfProductKeysFromRecommendations
  • ProductDao.readProducts
  • replaceProductKeysByProductsOnRecommendations

Подобно этому вы можете повторно использовать ProductDao.readProducts для

  • Клиент * --buys-- * Продукт или
  • ProductGroup 1 --- * Продукт

Ответ 2

Я думаю, что ваш код будет работать, но здесь речь идет об использовании ResultSetExtractor, который в основном предназначен для самой структуры JDBC, и для большинства случаев documentation рекомендует использовать RowMapper.

Таким образом, альтернативный подход состоял бы в том, чтобы в вашем DAO был метод, который выбирает и сопоставляет родительский объект. Затем для каждого объекта вызывается другой репозиторий или частный метод, который выбирает и сопоставляет дочерние объекты, а затем связывает дочерние объекты с родителями на основе вашего типа отношений (однонаправленного или двунаправленного). Этот подход также может позволить вам контролировать, хотите ли вы загружать дочерние объекты или нет.

Например, вы можете проверить приложение Spring PetClinic, которое класс SimpleJdbcClinic

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