【问题标题】:Spring Data R2DBC how to query hierarchical dataSpring Data R2DBC如何查询分层数据
【发布时间】:2023-03-15 04:20:01
【问题描述】:

我是响应式编程的新手。我必须开发一个简单的 Spring Boot 应用程序来返回一个包含公司详细信息及其所有子公司和员工的 json 响应

创建了一个spring boot应用(Spring Webflux + Spring data r2dbc)

使用下面的数据库表来表示公司和子公司和员工的关系(它是公司和子公司的层级关系,一个公司可以有 N 个子公司,每个子公司可以有另一个 N 个子公司子公司等)

公司

  • 身份证
  • 姓名
  • 地址

Company_SubCompany

​​>
  • 身份证
  • sub_company_id(上面公司表的外键引用id)

员工

  • 身份证
  • 姓名
  • 指定
  • company_id(上面公司表的外键引用id)

以下是代表上述表格的java模型类

公司.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 表中,超级公司用 id -1 表示。所以使用这个id我们现在可以得到超级母公司了。

通过以下服务代码,我现在能够获得第一级公司及其员工。但我不确定如何获取所有嵌套的子公司并添加到它

@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 个休假)。

【问题讨论】:

  • 感谢@AhmetOZKESEK。目前 spring data R2DBC 不支持关系。因此,对于这种情况,该链接似乎没有多大用处
  • 没错,我没有错过。另一方面,您的 Employee 类现在具有 companyId 字段/属性。是故意的还是只是复制/粘贴事故?
  • 另一方面,我在 Spring Data R2DBC 文档中看到的是,在我看来,我们可以尝试通过实现我们的存储库接口Converter&lt;Row, YourClass&gt; 来使用它,docs.spring.io/spring-data/r2dbc/docs/1.0.x/reference/html/…,它是有意思,有时间我会试试的。

标签: java asynchronous project-reactor spring-data-r2dbc r2dbc


【解决方案1】:

这段代码可以帮助你,这种方法从数据库调用中填充列表对象

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()))
            );

}

【讨论】:

    猜你喜欢
    • 2020-07-13
    • 2020-11-29
    • 2020-07-28
    • 1970-01-01
    • 2020-03-11
    • 2021-12-14
    • 1970-01-01
    • 2021-01-23
    • 2020-07-04
    相关资源
    最近更新 更多