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

我正在使用我的API中的标准构建器来获得结果.

我面临的问题是,当我传递student_group表中的任何可用文本时,我都会得到结果.当我给出NULL,所以我在student表中的lastRollResult为NULL时,我得到的是结果,但当我同时传递文本和NULL的组合时,我得不到结果.

我的API是这样的

Http://localhost:8080/student?query=grade:5,最后滚动结果%40成功%23失败

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

Http://localhost:8080/student?query=grade:5,lastRollResult%空

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

下面是我正在try 的内容以及我的代码的外观.

我的控制器.

控制器类:

  @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.

在这里,您可以看到,对于文本,我执行的是内部连接,但是在空值的情况下,我直接获取数据.这就是我得到这种回应的原因.如何修复此值.

以下是我的表格详细信息.

@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;
}

和AbstractStudent

@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以及文本.

推荐答案

不清楚您希望如何处理查询结果中的关系.如果您希望返回学生数据,而不考虑相关实体的存在,我认为您应该try 使用LEFT JOIN:

    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");
}

编辑:

如果此解决方案对您有效,则意味着您正在基于某些标准实现对实体Student的搜索,该标准可能包括也可能不包括相关实体Result.要实现这一点,您可以基于现有的条件输入,动态地将LEFT联接应用于条件.

您可以始终返回连接结果,但仍然可以很好地工作,并且可以为两个实体应用所有谓词:

    @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实体相关的谓词:

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

}

Java相关问答推荐

将Nimbus设置为计算机上运行的所有Java应用程序的默认外观

如何审查Java dtos中的自定义注释字段?

Java应用程序崩溃时试图读取联系人从电话

无法传递消费者<;>;实例

取消按钮,但没有任何操作方法引发和异常

我需要生成一个文件来整合每个特性执行的所有JSON结果

如何找到MongoDB文档并进行本地化?

如何在运行时动态创建表(使用Java、JPA、SprringBoot)

与Spring Boot相关的实体未正确保存

将响应转换为带值的键

PDFBox未加载内容

在学习Spring时,通过构造函数参数0表达了不满意的依赖关系

使用htmlunit和java单击按钮

Lombok@Nonnull是否也对供应商有影响?

在处理2个映射表时,没有更多的数据可从套接字读取

Java创建带有扩展通配符的抽象处理器

协同 routine 似乎并不比JVM线程占用更少的资源

JXBrowser是否支持加载Chrome扩展?

如何在Spring Boot Auth服务器上正确配置CORS?

一条Java记录可以保存多少个字段?