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

nafvub8i  于 5个月前  发布在  Spring
关注(0)|答案(1)|浏览(36)

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

字符串
您可以注意到,在Controller中,我正在构建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 */
}


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

gywdnpxw

gywdnpxw1#

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

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

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

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


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

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


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

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
   
      // Check if the search criteria contains Result entity
      if (criteria.getKey().equals("lastRollResult")) {   
        Join results = root.join("lastRoll", JoinType.INNER);
        return results.get("result");
      }
      // Result entity is no present in the search criteria
      return root.get(criteria.getKey());
  }

//Below toPredicate methods

}

相关问题