Spring Data R2DBC как запрашивать иерархические данные

Я новичок в реактивном программировании. Мне нужно разработать простое приложение для весенней загрузки, чтобы вернуть ответ json, содержащий сведения о компании со всеми ее дочерними компаниями и сотрудниками.

Создал приложение для весенней загрузки (Spring Webflux + Spring data r2dbc)

Использование следующих таблиц базы данных для представления отношений между компанией и дочерней компанией и сотрудником (это иерархические отношения с компанией и дочерней компанией, в которой компания может иметь количество дочерних компаний N, и каждая из этих дочерних компаний может иметь еще N количество дочерних компаний. и т. д. и т. д.)

Компания

  • id
  • имя
  • адрес

Company_SubCompany

  • id
  • sub_company_id (идентификатор ссылки на внешний ключ приведенной выше таблицы компании)

Работник

  • id
  • имя
  • обозначение
  • company_id (идентификатор ссылки на внешний ключ приведенной выше таблицы компании)

Ниже приведены классы модели Java для представления приведенных выше таблиц.

Company.java

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Company  implements Serializable { 
    private int id;
    private String name;
    private String address;  
    
    @With
    @Transient
    private List<Company> subCompanies;
    
    @With
    @Transient
    private List<Employee> employees;
}

Employee.java

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Employee  implements Serializable {    
    @Id
    private int id;
    private String name;
    private String designation;  
    
}

Создаются следующие репозитории

@Repository
public interface CompanyRepository extends ReactiveCrudRepository<Company, Integer> {

    @Query("select sub.sub_company_id from Company_SubCompany sub inner join  Company c on sub.sub_company_id = c.id   where sub.id = :id")
    Flux<Integer> findSubCompnayIds(int id);
    
    @Query("select * from   Company c  where id = :id")
    Mono<Company> findCompanyById(Integer id);

}

@Repository
public interface EmployeeRepository extends ReactiveCrudRepository<Employee, Integer> {

    @Query("select * from   Employee where company_id = :id")
    Flux<Employee> findEmployeeByCompanyId(Integer id);

}

В таблице Company_SubCompany суперкомпания представлена ​​идентификатором -1. Таким образом, используя этот идентификатор, мы теперь можем получить родительскую компанию.

С приведенным ниже кодом обслуживания я теперь могу получить первый уровень компании и ее сотрудников. Но я не уверен, как получить все вложенные дочерние компании и добавить к ним

@Service
public class ComanyService {
    
    @Autowired
    CompanyRepository companyRepository;
    
    @Autowired
    EmployeeRepository employeeRepository;

    public Flux<Company> findComapnyWithAllChilds() {

        Flux<Integer> childCompanyIds = companyRepository.findSubCompnayIds(-1);
        Flux<Company> companies = childCompanyIds.flatMap(p -> {
            return Flux.zip(companyRepository.findCompanyById(p),
                    employeeRepository.findEmployeeByCompanyId(p).collectList(),
                    (t1, t2) -> t1.withEmployees(t2));
        });

        return companies;
    }
}

Я новичок в реактивном функциональном программировании и r2dbc, поэтому, пожалуйста, помогите мне решить мою проблему. Если есть какой-либо другой лучший подход, мы также будем использовать его. Требование состоит в том, чтобы получить компанию, всех ее сотрудников и дочерние компании (до N уровня).


person Jijo Mathew    schedule 14.04.2020    source источник
comment
Просто начните здесь, vladmihalcea.com/tutorials/hibernate   -  person Ahmet OZKESEK    schedule 15.04.2020
comment
Спасибо @AhmetOZKESEK. В настоящее время весенние данные R2DBC не поддерживают отношения. Так что эта ссылка кажется не очень полезной для этого случая   -  person Jijo Mathew    schedule 15.04.2020
comment
Вы правы, я этого не пропустил. С другой стороны, у вашего класса Employee теперь есть поле companyId / attr. Это намеренно или просто случайно скопировано / вставлено?   -  person Ahmet OZKESEK    schedule 15.04.2020
comment
С другой стороны, в документе Spring Data R2DBC я увидел то, что мне кажется, что мы можем попробовать использовать Converter<Row, YourClass>, реализовав его в нашем интерфейсе репозитория, docs.spring.io/spring-data/r2dbc/docs/1.0.x/reference/html /, это интересно, попробую когда-нибудь.   -  person Ahmet OZKESEK    schedule 15.04.2020


Ответы (1)


этот код может вам помочь, этот подход заполняет объекты List из вызовов базы данных

public Flux<Company> findComapnyWithAllChilds(){
    return companyRepository.findAll()
            .flatMap(companies ->
                    Mono.just(companies)
                    .zipWith(employeeRepository.findEmployeeByCompanyId(companies.getId()).collectList())
                    .map(tupla -> tupla.getT1().withEmployees(tupla.getT2()))
                        .zipWith(anotherRepository.findAnotherByCompanyId(companies.getId()).collectList())
                        .map(tupla -> tupla.getT1().withAnother(tupla.getT2()))
            );

}

person Yosel    schedule 13.07.2020