spring 如何使用条件生成器处理一对多关系中的空值?

nafvub8i  于 2024-01-05  发布在  Spring
关注(0)|答案(1)|浏览(117)

如何使用Criteria Builder处理一对多关系中的空值。
我正在使用我的API中的标准生成器来获得结果。
我所面临的问题是当我传递的任何文本,这是在student_group表中,我得到的结果。当我给null,所以我的lastRollResult是null在student表中,我得到的结果,但当我传递的文本和null的组合,我没有得到结果。
我的API如下所示
http://本地主机:8080/学生?查询=成绩:5,上次滚动结果%40成功%23失败
在这种情况下,我可以获取数据
http://本地主机:8080/学生?查询=年级:5,上次滚动结果% null
在这种情况下,我无法获取数据
下面是我正在尝试的内容以及我的代码。
我的控制器。
控制器类别:

  1. @RequestMapping(method = RequestMethod.GET)
  2. public Page<StudentDTO> index(MySpecificationsBuilder builder,
  3. @PageableDefault(value = 25, page = 0) Pageable pageable) {
  4. Specification<Student> spec = builder.build();
  5. Page<Student> stu = studentService.findAll(spec, pageable);
  6. /** here some modification on retuen */
  7. }

字符串
您可以注意到,在Controller中,我正在构建MySpecificationsBuilder,所有的条件都在这里设置。

  1. public class MySpecificationsBuilder extends BaseSpecification<Student> {
  2. public MySpecificationsBuilder(final SearchCriteria criteria) {
  3. super(criteria);
  4. }
  5. @Override
  6. protected Expression<String> getPath(SearchCriteria criteria, Root<Student> root) {
  7. /** some other conditions */
  8. if (criteria.getKey().equals("lastRollResult")) {
  9. if (!"null".contains(criteria.getValue())) {
  10. Join results = root.join("lastRoll", JoinType.INNER); // In case of text (JoinType.INNER is enum of Inner.
  11. return results.get("result");
  12. }else{
  13. return root.get("lastRoll”); // in case of null
  14. }
  15. }
  16. return root.get(criteria.getKey());
  17. }
  18. /** below toPredicate methods */
  19. }


在MySpecificationsBuilder中,我正在进行一些其他的计算,作为resultConstant和toPredicate的结果。
在这里,你可以看到,对于文本,我在进行内部连接,但是对于null,我直接得到数据。所以,这就是我得到这个响应的原因。如何修正这个值。
这是我的表详细信息。

  1. @Entity
  2. @Data
  3. @DiscriminatorFormula("case when entity_type is null then ‘Student’ else entity_type end")
  4. @DiscriminatorValue("Student")
  5. public class Student extends AbstractStudent {
  6. @ManyToOne
  7. @Fetch(value = FetchMode.SELECT)
  8. @JoinColumn(name = "created_by_id", insertable = false, updatable = false)
  9. @EqualsAndHashCode.Exclude
  10. @ToString.Exclude
  11. @NotFound(action = NotFoundAction.IGNORE)
  12. User createdBy;
  13. @Transient
  14. private String name;
  15. @Transient
  16. private List<String> tags;
  17. }


抽象学生

  1. @RequiresAudit
  2. @Log4j2
  3. @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
  4. @Data
  5. @Entity
  6. @Table(name = "student_group")
  7. @DiscriminatorColumn(name = "entity_type", discriminatorType = DiscriminatorType.STRING)
  8. public class AbstractStudent extends BaseModel {
  9. @OneToMany(mappedBy = "student", fetch = FetchType.LAZY)
  10. @EqualsAndHashCode.Exclude
  11. @ToString.Exclude
  12. List<StudentMapping> studentMappings;
  13. @OneToMany(mappedBy = "student", fetch = FetchType.LAZY)
  14. @EqualsAndHashCode.Exclude
  15. @ToString.Exclude
  16. List<StudentDataMapping> studentDataMapping;
  17. @Id
  18. @GeneratedValue(strategy = GenerationType.IDENTITY)
  19. private Long id;
  20. @AuditColumn
  21. @Column(name = "last_roll_id")
  22. private Long lastRollId;
  23. @OneToMany(mappedBy = "student", fetch = FetchType.LAZY)
  24. @EqualsAndHashCode.student
  25. @ToString.Exclude
  26. private Set<TagUse> tagUses;
  27. @ManyToOne
  28. @Fetch(value = FetchMode.SELECT)
  29. @JoinColumn(name = "last_roll_id", referencedColumnName = "id", insertable = false, updatable = false)
  30. @EqualsAndHashCode.Exclude
  31. @ToString.Exclude
  32. @NotFound(action = NotFoundAction.IGNORE)
  33. private Result lastRoll;
  34. /** some other column defination */
  35. }


在“我的摘要”列中,可以有一对一的Map。
是否有任何解决方案,如组或任何where子句或任何其他东西,我可以俱乐部这两个参数,以获得结果的null以及文本。

gywdnpxw

gywdnpxw1#

查询结果中的关系如何处理还不清楚,如果不管相关实体是否存在都想返回students数据,我觉得应该试试左联接:

  1. Join results = root.join("lastRoll", JoinType.LEFT);
  2. return results.get("result");

字符串
也许你想实现这样的目标:

  1. if (criteria.getKey().equals("lastRollResult")) {
  2. Join results = root.join("lastRoll", JoinType.LEFT);
  3. return results.get("result");
  4. }


编辑:
如果此解决方案适用于您,则意味着您正在基于某些条件(可能包含也可能不包含相关实体Result)实现对实体Student的搜索。要实现此目标,您可以基于现有条件输入动态地将LEFT联接应用于条件。
您可以始终返回连接结果,并且仍然可以正常工作,并且您可以为两个实体应用所有 predicate :

  1. @Override
  2. protected Expression<String> getPath(SearchCriteria criteria, Root<Student> root) {
  3. // Some other conditions
  4. Join results = root.join("lastRoll", JoinType.INNER);
  5. return results.get("result");
  6. }


然而,在某些情况下,生成的SQL查询的性能会降低。如果你只在需要的时候处理连接包含,你会得到更好的查询和更好的性能,但是,你也需要动态地应用与Result实体相关的 predicate :

  1. public class MySpecificationsBuilder extends BaseSpecification<Student> {
  2. public MySpecificationsBuilder(final SearchCriteria criteria) {
  3. super(criteria);
  4. }
  5. @Override
  6. protected Expression<String> getPath(SearchCriteria criteria, Root<Student> root) {
  7. // Some other conditions
  8. // Check if the search criteria contains Result entity
  9. if (criteria.getKey().equals("lastRollResult")) {
  10. Join results = root.join("lastRoll", JoinType.INNER);
  11. return results.get("result");
  12. }
  13. // Result entity is no present in the search criteria
  14. return root.get(criteria.getKey());
  15. }
  16. //Below toPredicate methods
  17. }

展开查看全部

相关问题