目前,我正在尝试使用 Dataloader 模式 ( java-dataloader
) 、Java
、Spring Boot
和SPQR
来解决 N+1 问题Java Dataloader
。
我目前的实体设置如下:
@Setter
@Getter
@Entity
@NoArgsConstructor
@AllArgsConstructor
public class Employee implements Serializable {
private static final long serialVersionUID = 684733882540759135L;
@Id
@GeneratedValue
@Column(columnDefinition = "uuid", updatable = false)
@GraphQLQuery(name = "id", description = "A Person's Id")
private UUID id;
@NotNull(message = "There must be a Person's Name!")
@GraphQLQuery(name = "fullName", description = "A Person's Name")
private String fullName;
@NotNull(message = "A Person must have an Age!")
@GraphQLQuery(name = "age", description = "A Person's Age")
private int age;
@NotNull(message = "A Person must have a Vehicle!")
@GraphQLQuery(name = "personalVehicle", description = "A Person's Mode of Transport")
private Vehicle personalVehicle;
@ManyToOne(targetEntity = Company.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@GraphQLQuery(name = "company", description = "The Company a Person works for")
private Company company;
@GraphQLIgnore(reason = "None of your business!")
private String socialSecurityNumber;
public enum Vehicle {
CAR,
BUS,
VAN,
BICYCLE,
MOTORBIKE,
SCOOTER
}
}
这是公司对象(在上面的类中引用)
@Setter
@Getter
@Entity
@NoArgsConstructor
@AllArgsConstructor
public class Company implements Serializable {
private static final long serialVersionUID = -6007975840330441233L;
@Id
@GeneratedValue
@Column(columnDefinition = "uuid", updatable = false)
@GraphQLQuery(name = "id", description = "A Company's Id")
private UUID id;
@NotNull(message = "There must be a Company Name!")
@GraphQLQuery(name = "name", description = "A Company's Name")
private String name;
@Min(10000)
@NotNull(message = "You gotta tell us how rich you are!")
@GraphQLQuery(name = "balance", description = "A Company's Dollar")
private BigDecimal balance;
@NotNull(message = "There must be a Company Type!")
@GraphQLQuery(name = "type", description = "The type of company")
private CompanyType type;
public enum CompanyType {
PRIVATE_LIMITED,
SOLE_TRADER,
PUBLIC
}
}
我的 SPQR Resolvers/GraphQLApis 如图所示:
@Component
@GraphQLApi
@RequiredArgsConstructor
public class CompanyResolver {
private final CompanyDao companyDao;
@GraphQLQuery(name = "getAllCompanies")
public List<Company> getAllCompanies() {
return companyDao.findAll();
}
@GraphQLQuery(name = "getCompanyById")
public CompletableFuture<Company> getCompanyById(@GraphQLArgument(name = "id") @GraphQLNonNull @Valid UUID id, @GraphQLEnvironment ResolutionEnvironment env) {
DataLoader<UUID, Company> loader = env.dataFetchingEnvironment.getDataLoader("company");
return loader.load(id);
}
@GraphQLMutation(name = "saveCompany")
public Company saveCompany(@GraphQLArgument(name = "company") @GraphQLNonNull @Valid Company company) {
return companyDao.save(company);
}
@GraphQLMutation(name = "deleteCompany")
public void deleteCompany(@GraphQLArgument(name = "id") @GraphQLNonNull @Valid UUID companyId) {
companyDao.deleteById(companyId);
}
}
@GraphQLApi
@Component
@RequiredArgsConstructor
public class EmployeeResolver {
private final EmployeeDao employeeDao;
@GraphQLQuery(name = "getAllEmployees")
public List<Employee> getAllEmployees() {
return employeeDao.findAll();
}
@GraphQLQuery(name = "getEmployeeById")
public Optional<Employee> getEmployeeById(@GraphQLArgument(name = "id") @GraphQLNonNull @Valid UUID id) {
return employeeDao.findById(id);
}
@GraphQLMutation(name = "saveEmployee")
public Employee saveEmployee(@GraphQLArgument(name = "employee") @GraphQLNonNull @Valid Employee company) {
return employeeDao.save(company);
}
@GraphQLMutation(name = "deleteEmployee")
public void deleteEmployee(@GraphQLArgument(name = "id") @GraphQLNonNull @Valid UUID companyId) {
employeeDao.deleteById(companyId);
}
}
我的数据加载器都设置正确,但我需要Employee
实体的company
字段来使用数据加载器,如getCompanyById
查询中所示 - 以避免相关对象的 N+1 问题。
如果我完全错了,请说 - 我是 SPQR 的菜鸟。任何答案或澄清问题将不胜感激!谢谢!