0

我是来自与其他实体具有多对一关系的实体的查询数据。使用规范只能获取根的记录。但我也需要从关系实体中获取列。

我是 Spring Boot 的新手,正在尝试构建 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 { id: 1, reports_preset_filter : [ ] }

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

4

1 回答 1

0

发生的情况是 JPA@OneToMany获取策略在默认情况下是惰性的,这意味着引用字段只是“空”代理,仅当您使用 getter 从它们显式读取时才会填充。您可能希望保留此策略并仅获取此查询的字段。

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

实体图是特定持久性查询或操作的模板。它们在创建获取计划或同时检索的持久字段组时使用[..] 默认情况下,实体字段或属性是延迟获取的。开发人员将字段或属性指定为获取计划的一部分,持久性提供程序将急切地获取它们。

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

于 2019-08-26T13:15:11.353 回答