如何使用 Criteria Builder 处理一对多关系中的空值?

问题描述 投票:0回答:2

如何使用 Criteria Builder 处理一对多关系中的空值。

我正在使用 API 中的条件生成器来获取结果。

我面临的问题是,当我传递

student_group
表中可用的任何文本时,我得到了结果。当我给出 null 时,我的 lastRollResult 在
student
表中为 null,我得到结果,但是当我传递文本和 null 的组合时,我没有得到结果。

我的API是这样的

http://localhost:8080/student?query=grade:5,lastRollResult%40SUCCESS%23FAILURE

在这种情况下我能够获取数据

http://localhost:8080/student?query=grade:5,lastRollResult%null

在这种情况下我无法获取数据

现在这是我正在尝试的以及我的代码的样子。

我的控制器。

控制器类:

  @RequestMapping(method = RequestMethod.GET)
  public Page<StudentDTO> index(MySpecificationsBuilder builder,
                                @PageableDefault(value = 25, page = 0) Pageable pageable) {
    Specification<Student> spec = builder.build();
    Page<Student> stu = studentService.findAll(spec, pageable);

    /** here some modification on retuen */
  
  }

您可以注意到在控制器中我正在构建 MySpecificationsBuilder,其中所有标准都已设置。这是关于 MySpecificationsBuilder 的简介

     public class MySpecificationsBuilder extends BaseSpecification<Student> {
    
     public  MySpecificationsBuilder(final SearchCriteria criteria) {
        super(criteria);
      }

 
  @Override
  protected Expression<String> getPath(SearchCriteria criteria, Root<Student> root) {
    /** some other conditions */
   
 if (criteria.getKey().equals("lastRollResult"))  {    
   if (!"null".contains(criteria.getValue())) {
          Join results = root.join("lastRoll", JoinType.INNER); // In case of text (JoinType.INNER is enum of Inner.
          return results.get("result");
      }else{
        return root.get("lastRoll”); // in case of null
      }
    }
    return root.get(criteria.getKey());
  }

  /** below toPredicate methods  */

}

在 MySpecificationsBuilder 中,我正在做一些其他计算,如 resultConstant 和 toPredicate 结果。

在这里,正如您所看到的,在文本的情况下我正在执行内部连接,但在 null 的情况下我直接获取数据。这就是我收到此回复的原因。如何修复这个值。

这是我的桌子详细信息。

@Entity
@Data
@DiscriminatorFormula("case when entity_type is null then ‘Student’ else entity_type end")
@DiscriminatorValue("Student")
public class Student extends AbstractStudent {
  @ManyToOne
  @Fetch(value = FetchMode.SELECT)
  @JoinColumn(name = "created_by_id", insertable = false, updatable = false)
  @EqualsAndHashCode.Exclude
  @ToString.Exclude
  @NotFound(action = NotFoundAction.IGNORE)
  User createdBy;
  @Transient
  private String name;

  @Transient
  private List<String> tags;
}

和抽象学生

@RequiresAudit
@Log4j2
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Data
@Entity
@Table(name = "student_group")
@DiscriminatorColumn(name = "entity_type", discriminatorType = DiscriminatorType.STRING)
public class AbstractStudent extends BaseModel {

  @OneToMany(mappedBy = "student", fetch = FetchType.LAZY)
  @EqualsAndHashCode.Exclude
  @ToString.Exclude
  List<StudentMapping> studentMappings;
  
  @OneToMany(mappedBy = "student", fetch = FetchType.LAZY)
  @EqualsAndHashCode.Exclude
  @ToString.Exclude
  List<StudentDataMapping> studentDataMapping;
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  @AuditColumn
 
  @Column(name = "last_roll_id")
  private Long lastRollId;

  
  @OneToMany(mappedBy = "student", fetch = FetchType.LAZY)
  @EqualsAndHashCode.student
  @ToString.Exclude
  private Set<TagUse> tagUses;
  @ManyToOne
  @Fetch(value = FetchMode.SELECT)
  @JoinColumn(name = "last_roll_id", referencedColumnName = "id", insertable = false, updatable = false)
  @EqualsAndHashCode.Exclude
  @ToString.Exclude
  @NotFound(action = NotFoundAction.IGNORE)
  private Result lastRoll;

  /** some other column defination */
}

在我的摘要栏中您可以进行一对一的映射。

是否有任何解决方案,例如组或任何 where 子句或任何其他东西,我可以通过这些解决方案将这两个参数组合在一起以获得 null 和文本的结果。

java spring one-to-many hibernate-criteria
2个回答
0
投票

您可能需要修改 Criteria API 查询的构建方式。具体来说,您需要确保您的查询可以处理 lastRollResult 字段的空值和非空值。

// MySpecificationsBuilder

@Override
protected Expression<String> getPath(SearchCriteria criteria, Root<Student> root) {

    if (criteria.getKey().equals("lastRollResult")) {

        Join<Student, Result> resultsJoin = root.join("lastRoll", JoinType.LEFT);

        if (!"null".equals(criteria.getValue())) {

            // Handle non-null values

            return resultsJoin.get("result");

        } else {

            // Handle null values

            return builder.isNull(resultsJoin.get("result"));
        }
    }
    return root.get(criteria.getKey());
}

更新 toPredicate 方法:确保您的 toPredicate 方法在考虑空值和非空值的情况下正确构造查询谓词。


0
投票

不清楚要如何处理查询结果中的关系。如果你想返回学生数据而不管相关实体是否存在,我认为你应该尝试使用左连接:

    Join results = root.join("lastRoll", JoinType.LEFT); 
    return results.get("result");
© www.soinside.com 2019 - 2024. All rights reserved.