首页 > 解决方案 > Avoid duplicate code in criteria builder query in spring data jpa

问题描述

I am using Spring Boot (1.5.14.RELEASE) and Spring data Jpa with Java 1.8. I want to avoid duplicate code.

Below query fetches employee details. It's working fine.

Class EmployeeDAO:

  CriteriaBuilder cb = em.getCriteriaBuilder();
  CriteriaQuery<EmployeeDto> cq = cb.createQuery(EmployeeDto.class);
  Root<EmployeeInfo> root = cq.from(EmployeeInfo.class);
  Join<EmployeeInfo, SalaryInfo> SalaryType = root.join("SalaryInfo");
  Join<EmployeeInfo, CompanyInfo> Company = root.join("CompanyInfo");

  cq.select(cb.construct(EmployeeDto.class,
      root.get("FirstName"),
      SalaryType.get("Salary"),
      Company.get("CompanyName")))
      .where(specification.toPredicate(root, cq, cb))
      .orderBy(cb.asc(root.get("FirstName")));

Another function in same class in also making the almost 90% same criteria builder query as shown below:

  CriteriaBuilder cb = em.getCriteriaBuilder();
  CriteriaQuery<EmployeeDto> cq = cb.createQuery(EmployeeDto.class);
  Root<EmployeeInfo> root = cq.from(EmployeeInfo.class);
  Join<EmployeeInfo, SalaryInfo> SalaryType = root.join("SalaryInfo");
  Join<EmployeeInfo, CompanyInfo> Company = root.join("CompanyInfo");
  Join<EmployeeInfo, UserInfo> User = root.join("UserInfo");

  cq.select(cb.construct(EmployeeDto.class,
      root.get("FirstName"),
      SalaryType.get("Salary"),
      Company.get("CompanyName"),
      User.get("Age")))
      .where(specification.toPredicate(root, cq, cb))
      .orderBy(cb.asc(root.get("FirstName")));

The code in both function is same except that below code is making join with UserInfo table to get user age. All other code is duplicate. Can you tell me how can I avoid this duplicate code.

标签: springspring-boot

解决方案


像这样的东西:

public class EmployeeDAO {

EntityManager em;
Specification specification;

public void get(boolean withUsers) {
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<EmployeeDto> cq = cb.createQuery(EmployeeDto.class);
    Root<EmployeeInfo> root = cq.from(EmployeeInfo.class);
    Join<EmployeeInfo, SalaryInfo> salaryType = root.join("SalaryInfo");
    Join<EmployeeInfo, CompanyInfo> company = root.join("CompanyInfo");

    List<Selection> sels = new ArrayList<>();
    Collections.addAll(sels,
            root.get("FirstName"),
            salaryType.get("Salary"),
            company.get("CompanyName")
    );
    if (withUsers) {
        Join<EmployeeInfo, UserInfo> user = root.join("UserInfo");
        sels.add(user.get("Age"));
    }

    cq.select(cb.construct(EmployeeDto.class,
            sels.toArray(new Selection[0])
    ))
            .where(specification.toPredicate(root, cq, cb))
            .orderBy(cb.asc(root.get("FirstName")));
}

}


推荐阅读