使用 Specification as Query 从 @Entity 以及关系 table 获取记录

Fetch Records from @Entity as well as relation table using Specification as Query

我正在查询来自与其他实体具有多对一关系的实体的数据。 使用 Specification 只能获取 Root 的 Record。但我也需要从关系实体中获取该列。

我是 Spring 新手,正在尝试构建 API。

查询根总是引用实体,那么如何使用规范中的自定义查询。

return new Specification<CallMessage>() {

private static final long serialVersionUID = 1L;

@Override
public Predicate toPredicate(Root<CallMessage> root, 
               CriteriaQuery<?> query, CriteriaBuilder cb) 
     {

    List<Predicate> predicates = new ArrayList<>();
            In<Long> inClause = cb.in(root.get("bed_address"));
            inClause.value("XYZ");
            predicates.add(inClause);
            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
     }

}


@Entity(name = "calls")

public class CallMessage implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;


    @OneToMany(targetEntity = PresetModel.class, mappedBy = "id", orphanRemoval = false)
    private Set<PresetModel> presetModels;
}


@Entity(name = "reports_preset_filter")
public class PresetModel extends AuditModel{

   private static final long serialVersionUID = 1L;

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "id")
   private int id;
   private String preset_name;



    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name="call_id" ,nullable=false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JsonIgnore
    private CallMessage callMessage ;
}

虽然使用 JpaSpecificationExecutor 不能使用另一个查询来连接这两个表。有什么方法可以获取记录,例如- call_message{ 编号:1, reports_preset_filter:[ ] }

我正在尝试使用多个谓词构建过滤器 API,为了放在这里,我已经削减了谓词列表以及实体的其他列。

发生的是 JPA @OneToMany 获取策略默认情况下是惰性的,这意味着引用字段只是 "empty" 代理,仅当您使用 getter.您可能希望保留此策略并仅为此查询获取字段。

一个优雅的解决方案是创建一个带有实体图的获取计划:

Entity graphs are templates for a particular Persistence query or operation. They are used when creating fetch plans, or groups of persistent fields that are retrieved at the same time[..] By default, entity fields or properties are fetched lazily. Developers specify fields or properties as part of a fetch plan, and the persistence provider will fetch them eagerly.

https://docs.oracle.com/javaee/7/tutorial/persistence-entitygraphs.htm

这是一个包含一些详细信息字段的主实体的代码示例:

@NamedEntityGraph(
  name = "post-entity-graph-with-comment-users",
  attributeNodes = {
    @NamedAttributeNode("subject"),
    @NamedAttributeNode(value = "comments", subgraph = "comments-subgraph"),
  },
  subgraphs = {
    @NamedSubgraph(
      name = "comments-subgraph",
      attributeNodes = {
        @NamedAttributeNode("user")
      }
    )
  }
)
@Entity
public class Post {
    @Id
    private Long id;
    private String subject;
    @OneToMany(mappedBy = "post")
    private List<Comment> comments;
}

@Entity
public class Comment {
    @Id
    private Long id;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn
    private User user;
    //...
}

然后你可以有一个 SimpleJpaRepository 子类覆盖

@Override
    public List<T> findAll(Specification<T> spec, Sort sort, EntityGraph.EntityGraphType entityGraphType, String entityGraphName) {
        TypedQuery<T> query = getQuery(spec, sort);
        query.setHint(entityGraphType.getKey(), em.getEntityGraph(entityGraphName));
        return query.getResultList();
    }

因此 运行 一个 Specification 也加载与评论相关的用户:

List<Post> results = myRepository.findAll(mySpecification, EntityGraph.EntityGraphType.LOAD, "post-entity-graph-with-comment-users");

https://www.baeldung.com/jpa-entity-graph