Позволяет ли Spring Data Jdbc объединить внешний ключ, а не идентификатор?

Пробовал много вариантов, но все время у меня были неправильные соединения. вместо того, чтобы получить фактическое имя_статуса по его идентификатору, указанному в столбце 'status' таблицы supplier_contracts, репозиторий возвращает идентификаторы соединения двух таблиц. Итак, как мне получить имя_статуса по int столбца статуса supplierContractRepository.findById (3L)?

Статусы сущности

 CREATE TABLE `contract_statuses` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) NOT NULL,
  PRIMARY KEY (`id`)
);

public class ContractStatuses {
  
    @Id
    Integer id;
    String name;

    public ContractStatuses(int id, String name) {
        this.id = id;
        this.name = name;
    }
} 

Организация по контрактам

    CREATE TABLE `suppliers_contracts` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `supplier` bigint(20) NOT NULL,
      `cabs_id` int(11) DEFAULT NULL,
      `start_date` date DEFAULT NULL,
      `end_date` date DEFAULT NULL,
      `attorny_end_date` date DEFAULT NULL,
      `number_of_payments` int(11) DEFAULT NULL,
      `payment_amount` int(11) DEFAULT NULL,
      `comments` varchar(2000) DEFAULT NULL,
      `close_date` timestamp NULL DEFAULT NULL,
      `status` int(11) NOT NULL,
      `created_on` timestamp NOT NULL DEFAULT current_timestamp(),
      PRIMARY KEY (`id`)
    );

@Table("suppliers_contracts")
public class SupplierContract {
    @Id
    Long id;
    Long supplier;
    Long cabsId;
    Date startDate;
    Date endDate;
    int paymentAmount;
    Date attornyEndDate;
    int numberOfPayments;
    String comments;
    Date closeDate;
    @MappedCollection(idColumn = "id")
    ContractStatuses status;
   
    public SupplierContract(Long id, Long supplier, Long cabsId, Date startDate, Date endDate,Date attornyEndDate, int numberOfPayments, int paymentAmount,
                            String comments, Date closeDate,ContractStatuses status) {
        this.id = id;
        this.supplier = supplier;
        this.cabsId = cabsId;
        this.startDate = startDate;
        this.endDate = endDate;
        this.attornyEndDate = attornyEndDate;
        this.numberOfPayments = numberOfPayments;
        this.paymentAmount = paymentAmount;
        this.comments = comments;
        this.closeDate = closeDate;
        this.status = status;

    }
}
        //Getters and setters here

@GetMapping("/getContracts")
    public Optional<SupplierContract> getSupp(){
       Optional<SupplierContract>  contract = supplierContractRepository.findById(3L);
        return contract ;
    }

person Haim Klainman    schedule 18.09.2020    source источник


Ответы (2)


У вас есть разные варианты:

  1. Вариант по умолчанию - загрузить статус отдельным вызовом в отдельный ContractStatusRepository. Поскольку эти статусы могут меняться не очень часто, вы можете рассмотреть возможность кеширования для этого.

  2. Если вам нужен только статус и вас не интересует контракт, вы можете добавить дополнительный метод в свой репозиторий с аннотацией @Query, которая выбирает два поля статуса на основе id контракта с использованием соединения SQL.

  3. Этот работает только для доступа только для чтения! Вы можете создать еще один объект ReadOnlyContract, который содержит ContractStatuses ссылку, помеченную как встроенный атрибут. Теперь вы можете сопоставить это с представлением, содержащим дополнительные поля статуса. Чтобы избежать случайного использования методов записи, вы должны унаследовать репозиторий от Repository и добавить только те методы чтения, которые вам действительно нужны.

person Jens Schauder    schedule 23.09.2020
comment
спасибо, но мне явно чего-то не хватает, потому что когда я добавил @Embedded(onEmpty = USE_NULL) ContractStatuses statuses;, я получаю A database object name must not be null or empty или Unknown column 'suppliers_contracts.name' in 'field list' в зависимости от того, как я сформировал объект .. - person Haim Klainman; 25.09.2020
comment
Похоже, представление не соответствует ожидаемой структуре. Не могли бы вы создать новый вопрос со структурой объекта, представлением и трассировкой стека? - person Jens Schauder; 26.09.2020
comment
stackoverflow.com/ questions / 64076453 / - person Haim Klainman; 26.09.2020

Вы должны использовать отношения БД между классами SupplierContract и ContractStatuses.

т.е. используйте ContractStatuses contractStatuses; вместо int status; и используйте отношение "один ко многим" после этого, когда вы запрашиваете findAll(), вы получите ContractStatuses, откуда вы можете получить status_name.

person Aqib Nabi    schedule 18.09.2020
comment
Но отношение много к одному, потому что SupplierContract может иметь только один status_id в определенный момент времени, в то время как некоторый status_id, очевидно, может иметь много контрактов .. так как это может быть отражено, когда я хочу выполнить supplierContract.findAll () и получить столбец status_name также? - person Haim Klainman; 19.09.2020
comment
Вы должны объявить отношения на обеих сторонах @ManyToOne на стороне SupplierContract и @OneToMany на стороне ContractStatuses. см. (baeldung.com/spring-data-rest-relationships) для получения дополнительной информации Информация - person Aqib Nabi; 21.09.2020
comment
В данных Spring нет аннотации @ManyToOne jdbc - person Haim Klainman; 21.09.2020
comment
Этот ответ, похоже, предполагает JPA, который не используется в вопросе. - person Jens Schauder; 23.09.2020